├── .github ├── FUNDING.yml └── workflows │ └── dependency-review.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── Procfile ├── README.md ├── app.json ├── bot.py ├── config.py ├── database └── database.py ├── helper_func.py ├── heroku.yml ├── main.py ├── plugins ├── __init__.py ├── admin.py ├── banuser.py ├── broadcast.py ├── cbb.py ├── channel_post.py ├── link_generator.py ├── request_fsub.py ├── route.py ├── start.py └── useless.py └── requirements.txt /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: ['https://github.com/sponsors/Codflix-bots'] 4 | -------------------------------------------------------------------------------- /.github/workflows/dependency-review.yml: -------------------------------------------------------------------------------- 1 | # Dependency Review Action 2 | # 3 | # This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. 4 | # 5 | # Source repository: https://github.com/actions/dependency-review-action 6 | # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement 7 | name: 'Dependency Review' 8 | on: [pull_request] 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | dependency-review: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: 'Checkout Repository' 18 | uses: actions/checkout@v3 19 | - name: 'Dependency Review' 20 | uses: actions/dependency-review-action@v2 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Python template 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | cover/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | .pybuilder/ 77 | target/ 78 | 79 | # Jupyter Notebook 80 | .ipynb_checkpoints 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | # For a library or package, you might want to ignore these files since the code is 88 | # intended to run in multiple environments; otherwise, check them in: 89 | # .python-version 90 | 91 | # pipenv 92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 95 | # install all needed dependencies. 96 | #Pipfile.lock 97 | 98 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 99 | __pypackages__/ 100 | 101 | # Celery stuff 102 | celerybeat-schedule 103 | celerybeat.pid 104 | 105 | # SageMath parsed files 106 | *.sage.py 107 | 108 | # Environments 109 | .env 110 | .venv 111 | env/ 112 | venv/ 113 | ENV/ 114 | env.bak/ 115 | venv.bak/ 116 | 117 | # Spyder project settings 118 | .spyderproject 119 | .spyproject 120 | 121 | # Rope project settings 122 | .ropeproject 123 | 124 | # mkdocs documentation 125 | /site 126 | 127 | # mypy 128 | .mypy_cache/ 129 | .dmypy.json 130 | dmypy.json 131 | 132 | # Pyre type checker 133 | .pyre/ 134 | 135 | # pytype static type analyzer 136 | .pytype/ 137 | 138 | # Cython debug symbols 139 | cython_debug/ 140 | 141 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.10-slim 2 | WORKDIR /app 3 | 4 | COPY requirements.txt requirements.txt 5 | RUN pip3 install -r requirements.txt 6 | 7 | COPY . . 8 | 9 | CMD python3 main.py 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Codeflix-Bots 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: python3 main.py 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ━━━━━━━━━━━━━━━━━━━━ 2 | 3 |
8 |
9 |
/batch
& /custom_batch
22 | • Link Generator: Instantly generate direct links with /genlink
23 | • Broadcast Tools: Send messages or media to all users using /broadcast
, /dbroadcast
, or /pbroadcast
24 | • Auto File Deletion: Control auto-delete with /dlt_time
& /check_dlt_time
25 | • User Management: Ban/unban users and view banlist via /ban
, /unban
, and /banlist
26 | • Multi Force Subscription: Add, delete, and manage multiple Force Sub channels with /addchnl
, /delchnl
, /listchnl
27 | • Admin Control: Add or remove admins with /add_admin
, /deladmin
, and view list via /admins
28 |
29 | • Bot Analytics: Get stats and uptime via /stats
, user info with /users
, and database count via /count
30 | • Deployment Ready: Easily deploy on Heroku or Koyeb in minutes
31 |
32 | ✨ More features & enhancements coming soon...
33 | 127 |
128 | git clone https://github.com/Codeflix-Bots/FileStore 129 | # Install Packages 130 | pip3 install -U -r requirements.txt 131 | Edit info.py with variables as given below then run bot 132 | python3 bot.py 133 |134 | 135 |
Bᴏᴛ Rᴇsᴛᴀʀᴛᴇᴅ by @Codeflix_Bots") 63 | except: pass 64 | 65 | async def stop(self, *args): 66 | await super().stop() 67 | self.LOGGER(__name__).info("Bot stopped.") 68 | 69 | def run(self): 70 | """Run the bot.""" 71 | loop = asyncio.get_event_loop() 72 | loop.run_until_complete(self.start()) 73 | self.LOGGER(__name__).info("Bot is now running. Thanks to @rohit_1888") 74 | try: 75 | loop.run_forever() 76 | except KeyboardInterrupt: 77 | self.LOGGER(__name__).info("Shutting down...") 78 | finally: 79 | loop.run_until_complete(self.stop()) 80 | 81 | # 82 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >. 83 | # 84 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project, 85 | # and is released under the MIT License. 86 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE > 87 | # 88 | # All rights reserved. 89 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888 2 | # Ask Doubt on telegram @CodeflixSupport 3 | # 4 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >. 5 | # 6 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project, 7 | # and is released under the MIT License. 8 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE > 9 | # 10 | # All rights reserved. 11 | # 12 | 13 | import os 14 | from os import environ,getenv 15 | import logging 16 | from logging.handlers import RotatingFileHandler 17 | 18 | #rohit_1888 on Tg 19 | #-------------------------------------------- 20 | #Bot token @Botfather 21 | TG_BOT_TOKEN = os.environ.get("TG_BOT_TOKEN", "8154426339") 22 | APP_ID = int(os.environ.get("APP_ID", "")) #Your API ID from my.telegram.org 23 | API_HASH = os.environ.get("API_HASH", "") #Your API Hash from my.telegram.org 24 | #-------------------------------------------- 25 | 26 | CHANNEL_ID = int(os.environ.get("CHANNEL_ID", "-1002170811388")) #Your db channel Id 27 | OWNER = os.environ.get("OWNER", "sewxiy") # Owner username without @ 28 | OWNER_ID = int(os.environ.get("OWNER_ID", "7328629001")) # Owner id 29 | #-------------------------------------------- 30 | PORT = os.environ.get("PORT", "8001") 31 | #-------------------------------------------- 32 | DB_URI = os.environ.get("DATABASE_URL", "") 33 | DB_NAME = os.environ.get("DATABASE_NAME", "Cluooo") 34 | #-------------------------------------------- 35 | FSUB_LINK_EXPIRY = int(os.getenv("FSUB_LINK_EXPIRY", "10")) # 0 means no expiry 36 | BAN_SUPPORT = os.environ.get("BAN_SUPPORT", "https://t.me/CodeflixSupport") 37 | TG_BOT_WORKERS = int(os.environ.get("TG_BOT_WORKERS", "200")) 38 | #-------------------------------------------- 39 | START_PIC = os.environ.get("START_PIC", "https://telegra.ph/file/ec17880d61180d3312d6a.jpg") 40 | FORCE_PIC = os.environ.get("FORCE_PIC", "https://telegra.ph/file/e292b12890b8b4b9dcbd1.jpg") 41 | #-------------------------------------------- 42 | 43 | #-------------------------------------------- 44 | HELP_TXT = "
ᴛʜɪs ɪs ᴀɴ ғɪʟᴇ ᴛᴏ ʟɪɴᴋ ʙᴏᴛ ᴡᴏʀᴋ ғᴏʀ @Nova_Flix\n\n❏ ʙᴏᴛ ᴄᴏᴍᴍᴀɴᴅs\n├/start : sᴛᴀʀᴛ ᴛʜᴇ ʙᴏᴛ\n├/about : ᴏᴜʀ Iɴғᴏʀᴍᴀᴛɪᴏɴ\n└/help : ʜᴇʟᴘ ʀᴇʟᴀᴛᴇᴅ ʙᴏᴛ\n\n sɪᴍᴘʟʏ ᴄʟɪᴄᴋ ᴏɴ ʟɪɴᴋ ᴀɴᴅ sᴛᴀʀᴛ ᴛʜᴇ ʙᴏᴛ ᴊᴏɪɴ ʙᴏᴛʜ ᴄʜᴀɴɴᴇʟs ᴀɴᴅ ᴛʀʏ ᴀɢᴀɪɴ ᴛʜᴀᴛs ɪᴛ.....!\n\n ᴅᴇᴠᴇʟᴏᴘᴇᴅ ʙʏ sᴜʙᴀʀᴜ" 45 | ABOUT_TXT = "
◈ ᴄʀᴇᴀᴛᴏʀ: Yato\n◈ ꜰᴏᴜɴᴅᴇʀ ᴏꜰ : ᴏᴛᴀᴋᴜғʟɪx ɴᴇᴛᴡᴏʀᴋ\n◈ ᴀɴɪᴍᴇ ᴄʜᴀɴɴᴇʟ : ᴀɴɪᴍᴇ ᴄʀᴜɪsᴇ\n◈ sᴇʀɪᴇs ᴄʜᴀɴɴᴇʟ : ᴡᴇʙsᴇʀɪᴇs ғʟɪx\n◈ ᴀᴅᴜʟᴛ ᴍᴀɴʜᴡᴀ : ᴘᴏʀɴʜᴡᴀs\n◈ ᴅᴇᴠᴇʟᴏᴘᴇʀ : subaru" 46 | #-------------------------------------------- 47 | #-------------------------------------------- 48 | START_MSG = os.environ.get("START_MESSAGE", "ʜᴇʟʟᴏ {first}\n\n
ɪ ᴀᴍ ғɪʟᴇ sᴛᴏʀᴇ ʙᴏᴛ, ɪ ᴄᴀɴ sᴛᴏʀᴇ ᴘʀɪᴠᴀᴛᴇ ғɪʟᴇs ɪɴ sᴘᴇᴄɪғɪᴇᴅ ᴄʜᴀɴɴᴇʟ ᴀɴᴅ ᴏᴛʜᴇʀ ᴜsᴇʀs ᴄᴀɴ ᴀᴄᴄᴇss ɪᴛ ғʀᴏᴍ sᴘᴇᴄɪᴀʟ ʟɪɴᴋ.") 49 | FORCE_MSG = os.environ.get("FORCE_SUB_MESSAGE", "ʜᴇʟʟᴏ {first}\n\nᴊᴏɪɴ ᴏᴜʀ ᴄʜᴀɴɴᴇʟs ᴀɴᴅ ᴛʜᴇɴ ᴄʟɪᴄᴋ ᴏɴ ʀᴇʟᴏᴀᴅ button ᴛᴏ ɢᴇᴛ ʏᴏᴜʀ ʀᴇǫᴜᴇꜱᴛᴇᴅ ꜰɪʟᴇ.") 50 | 51 | CMD_TXT = """
» ᴀᴅᴍɪɴ ᴄᴏᴍᴍᴀɴᴅs:52 | 53 | ›› /dlt_time : sᴇᴛ ᴀᴜᴛᴏ ᴅᴇʟᴇᴛᴇ ᴛɪᴍᴇ 54 | ›› /check_dlt_time : ᴄʜᴇᴄᴋ ᴄᴜʀʀᴇɴᴛ ᴅᴇʟᴇᴛᴇ ᴛɪᴍᴇ 55 | ›› /dbroadcast : ʙʀᴏᴀᴅᴄᴀsᴛ ᴅᴏᴄᴜᴍᴇɴᴛ / ᴠɪᴅᴇᴏ 56 | ›› /ban : ʙᴀɴ ᴀ ᴜꜱᴇʀ 57 | ›› /unban : ᴜɴʙᴀɴ ᴀ ᴜꜱᴇʀ 58 | ›› /banlist : ɢᴇᴛ ʟɪsᴛ ᴏꜰ ʙᴀɴɴᴇᴅ ᴜꜱᴇʀs 59 | ›› /addchnl : ᴀᴅᴅ ꜰᴏʀᴄᴇ sᴜʙ ᴄʜᴀɴɴᴇʟ 60 | ›› /delchnl : ʀᴇᴍᴏᴠᴇ ꜰᴏʀᴄᴇ sᴜʙ ᴄʜᴀɴɴᴇʟ 61 | ›› /listchnl : ᴠɪᴇᴡ ᴀᴅᴅᴇᴅ ᴄʜᴀɴɴᴇʟs 62 | ›› /fsub_mode : ᴛᴏɢɢʟᴇ ꜰᴏʀᴄᴇ sᴜʙ ᴍᴏᴅᴇ 63 | ›› /pbroadcast : sᴇɴᴅ ᴘʜᴏᴛᴏ ᴛᴏ ᴀʟʟ ᴜꜱᴇʀs 64 | ›› /add_admin : ᴀᴅᴅ ᴀɴ ᴀᴅᴍɪɴ 65 | ›› /deladmin : ʀᴇᴍᴏᴠᴇ ᴀɴ ᴀᴅᴍɪɴ 66 | ›› /admins : ɢᴇᴛ ʟɪsᴛ ᴏꜰ ᴀᴅᴍɪɴs 67 | """ 68 | #-------------------------------------------- 69 | CUSTOM_CAPTION = os.environ.get("CUSTOM_CAPTION", "• ʙʏ @nova_flix") #set your Custom Caption here, Keep None for Disable Custom Caption 70 | PROTECT_CONTENT = True if os.environ.get('PROTECT_CONTENT', "False") == "True" else False #set True if you want to prevent users from forwarding files from bot 71 | #-------------------------------------------- 72 | #Set true if you want Disable your Channel Posts Share button 73 | DISABLE_CHANNEL_BUTTON = os.environ.get("DISABLE_CHANNEL_BUTTON", None) == 'True' 74 | #-------------------------------------------- 75 | BOT_STATS_TEXT = "BOT UPTIME\n{uptime}" 76 | USER_REPLY_TEXT = "ʙᴀᴋᴋᴀ ! ʏᴏᴜ ᴀʀᴇ ɴᴏᴛ ᴍʏ ꜱᴇɴᴘᴀɪ!!" 77 | #-------------------------------------------- 78 | 79 | 80 | LOG_FILE_NAME = "filesharingbot.txt" 81 | 82 | logging.basicConfig( 83 | level=logging.INFO, 84 | format="[%(asctime)s - %(levelname)s] - %(name)s - %(message)s", 85 | datefmt='%d-%b-%y %H:%M:%S', 86 | handlers=[ 87 | RotatingFileHandler( 88 | LOG_FILE_NAME, 89 | maxBytes=50000000, 90 | backupCount=10 91 | ), 92 | logging.StreamHandler() 93 | ] 94 | ) 95 | logging.getLogger("pyrogram").setLevel(logging.WARNING) 96 | 97 | 98 | def LOGGER(name: str) -> logging.Logger: 99 | return logging.getLogger(name) 100 | 101 | -------------------------------------------------------------------------------- /database/database.py: -------------------------------------------------------------------------------- 1 | #Codeflix_Botz 2 | #rohit_1888 on Tg 3 | 4 | import motor, asyncio 5 | import motor.motor_asyncio 6 | import time 7 | import pymongo, os 8 | from config import DB_URI, DB_NAME 9 | from bot import Bot 10 | import logging 11 | from datetime import datetime, timedelta 12 | 13 | dbclient = pymongo.MongoClient(DB_URI) 14 | database = dbclient[DB_NAME] 15 | 16 | logging.basicConfig(level=logging.INFO) 17 | 18 | 19 | class Rohit: 20 | 21 | def __init__(self, DB_URI, DB_NAME): 22 | self.dbclient = motor.motor_asyncio.AsyncIOMotorClient(DB_URI) 23 | self.database = self.dbclient[DB_NAME] 24 | 25 | self.channel_data = self.database['channels'] 26 | self.admins_data = self.database['admins'] 27 | self.user_data = self.database['users'] 28 | self.banned_user_data = self.database['banned_user'] 29 | self.autho_user_data = self.database['autho_user'] 30 | self.del_timer_data = self.database['del_timer'] 31 | self.fsub_data = self.database['fsub'] 32 | self.rqst_fsub_data = self.database['request_forcesub'] 33 | self.rqst_fsub_Channel_data = self.database['request_forcesub_channel'] 34 | 35 | 36 | 37 | # USER DATA 38 | async def present_user(self, user_id: int): 39 | found = await self.user_data.find_one({'_id': user_id}) 40 | return bool(found) 41 | 42 | async def add_user(self, user_id: int): 43 | await self.user_data.insert_one({'_id': user_id}) 44 | return 45 | 46 | async def full_userbase(self): 47 | user_docs = await self.user_data.find().to_list(length=None) 48 | user_ids = [doc['_id'] for doc in user_docs] 49 | return user_ids 50 | 51 | async def del_user(self, user_id: int): 52 | await self.user_data.delete_one({'_id': user_id}) 53 | return 54 | 55 | 56 | # ADMIN DATA 57 | async def admin_exist(self, admin_id: int): 58 | found = await self.admins_data.find_one({'_id': admin_id}) 59 | return bool(found) 60 | 61 | async def add_admin(self, admin_id: int): 62 | if not await self.admin_exist(admin_id): 63 | await self.admins_data.insert_one({'_id': admin_id}) 64 | return 65 | 66 | async def del_admin(self, admin_id: int): 67 | if await self.admin_exist(admin_id): 68 | await self.admins_data.delete_one({'_id': admin_id}) 69 | return 70 | 71 | async def get_all_admins(self): 72 | users_docs = await self.admins_data.find().to_list(length=None) 73 | user_ids = [doc['_id'] for doc in users_docs] 74 | return user_ids 75 | 76 | 77 | # BAN USER DATA 78 | async def ban_user_exist(self, user_id: int): 79 | found = await self.banned_user_data.find_one({'_id': user_id}) 80 | return bool(found) 81 | 82 | async def add_ban_user(self, user_id: int): 83 | if not await self.ban_user_exist(user_id): 84 | await self.banned_user_data.insert_one({'_id': user_id}) 85 | return 86 | 87 | async def del_ban_user(self, user_id: int): 88 | if await self.ban_user_exist(user_id): 89 | await self.banned_user_data.delete_one({'_id': user_id}) 90 | return 91 | 92 | async def get_ban_users(self): 93 | users_docs = await self.banned_user_data.find().to_list(length=None) 94 | user_ids = [doc['_id'] for doc in users_docs] 95 | return user_ids 96 | 97 | 98 | 99 | # AUTO DELETE TIMER SETTINGS 100 | async def set_del_timer(self, value: int): 101 | existing = await self.del_timer_data.find_one({}) 102 | if existing: 103 | await self.del_timer_data.update_one({}, {'$set': {'value': value}}) 104 | else: 105 | await self.del_timer_data.insert_one({'value': value}) 106 | 107 | async def get_del_timer(self): 108 | data = await self.del_timer_data.find_one({}) 109 | if data: 110 | return data.get('value', 600) 111 | return 0 112 | 113 | 114 | # CHANNEL MANAGEMENT 115 | async def channel_exist(self, channel_id: int): 116 | found = await self.fsub_data.find_one({'_id': channel_id}) 117 | return bool(found) 118 | 119 | async def add_channel(self, channel_id: int): 120 | if not await self.channel_exist(channel_id): 121 | await self.fsub_data.insert_one({'_id': channel_id}) 122 | return 123 | 124 | async def rem_channel(self, channel_id: int): 125 | if await self.channel_exist(channel_id): 126 | await self.fsub_data.delete_one({'_id': channel_id}) 127 | return 128 | 129 | async def show_channels(self): 130 | channel_docs = await self.fsub_data.find().to_list(length=None) 131 | channel_ids = [doc['_id'] for doc in channel_docs] 132 | return channel_ids 133 | 134 | 135 | # Get current mode of a channel 136 | async def get_channel_mode(self, channel_id: int): 137 | data = await self.fsub_data.find_one({'_id': channel_id}) 138 | return data.get("mode", "off") if data else "off" 139 | 140 | # Set mode of a channel 141 | async def set_channel_mode(self, channel_id: int, mode: str): 142 | await self.fsub_data.update_one( 143 | {'_id': channel_id}, 144 | {'$set': {'mode': mode}}, 145 | upsert=True 146 | ) 147 | 148 | # REQUEST FORCE-SUB MANAGEMENT 149 | 150 | # Add the user to the set of users for a specific channel 151 | async def req_user(self, channel_id: int, user_id: int): 152 | try: 153 | await self.rqst_fsub_Channel_data.update_one( 154 | {'_id': int(channel_id)}, 155 | {'$addToSet': {'user_ids': int(user_id)}}, 156 | upsert=True 157 | ) 158 | except Exception as e: 159 | print(f"[DB ERROR] Failed to add user to request list: {e}") 160 | 161 | 162 | # Method 2: Remove a user from the channel set 163 | async def del_req_user(self, channel_id: int, user_id: int): 164 | # Remove the user from the set of users for the channel 165 | await self.rqst_fsub_Channel_data.update_one( 166 | {'_id': channel_id}, 167 | {'$pull': {'user_ids': user_id}} 168 | ) 169 | 170 | # Check if the user exists in the set of the channel's users 171 | async def req_user_exist(self, channel_id: int, user_id: int): 172 | try: 173 | found = await self.rqst_fsub_Channel_data.find_one({ 174 | '_id': int(channel_id), 175 | 'user_ids': int(user_id) 176 | }) 177 | return bool(found) 178 | except Exception as e: 179 | print(f"[DB ERROR] Failed to check request list: {e}") 180 | return False 181 | 182 | 183 | # Method to check if a channel exists using show_channels 184 | async def reqChannel_exist(self, channel_id: int): 185 | # Get the list of all channel IDs from the database 186 | channel_ids = await self.show_channels() 187 | #print(f"All channel IDs in the database: {channel_ids}") 188 | 189 | # Check if the given channel_id is in the list of channel IDs 190 | if channel_id in channel_ids: 191 | #print(f"Channel {channel_id} found in the database.") 192 | return True 193 | else: 194 | #print(f"Channel {channel_id} NOT found in the database.") 195 | return False 196 | 197 | 198 | db = Rohit(DB_URI, DB_NAME) 199 | -------------------------------------------------------------------------------- /helper_func.py: -------------------------------------------------------------------------------- 1 | #(©)CodeFlix_Bots 2 | #rohit_1888 on Tg #Dont remove this line 3 | 4 | import base64 5 | import re 6 | import asyncio 7 | import time 8 | from pyrogram import filters 9 | from pyrogram.enums import ChatMemberStatus 10 | from config import * 11 | from pyrogram.errors.exceptions.bad_request_400 import UserNotParticipant 12 | from pyrogram.errors import FloodWait 13 | from database.database import * 14 | 15 | 16 | 17 | #used for cheking if a user is admin ~Owner also treated as admin level 18 | async def check_admin(filter, client, update): 19 | try: 20 | user_id = update.from_user.id 21 | return any([user_id == OWNER_ID, await db.admin_exist(user_id)]) 22 | except Exception as e: 23 | print(f"! Exception in check_admin: {e}") 24 | return False 25 | 26 | async def is_subscribed(client, user_id): 27 | channel_ids = await db.show_channels() 28 | 29 | if not channel_ids: 30 | return True 31 | 32 | if user_id == OWNER_ID: 33 | return True 34 | 35 | for cid in channel_ids: 36 | if not await is_sub(client, user_id, cid): 37 | # Retry once if join request might be processing 38 | mode = await db.get_channel_mode(cid) 39 | if mode == "on": 40 | await asyncio.sleep(2) # give time for @on_chat_join_request to process 41 | if await is_sub(client, user_id, cid): 42 | continue 43 | return False 44 | 45 | return True 46 | 47 | 48 | async def is_sub(client, user_id, channel_id): 49 | try: 50 | member = await client.get_chat_member(channel_id, user_id) 51 | status = member.status 52 | #print(f"[SUB] User {user_id} in {channel_id} with status {status}") 53 | return status in { 54 | ChatMemberStatus.OWNER, 55 | ChatMemberStatus.ADMINISTRATOR, 56 | ChatMemberStatus.MEMBER 57 | } 58 | 59 | except UserNotParticipant: 60 | mode = await db.get_channel_mode(channel_id) 61 | if mode == "on": 62 | exists = await db.req_user_exist(channel_id, user_id) 63 | #print(f"[REQ] User {user_id} join request for {channel_id}: {exists}") 64 | return exists 65 | #print(f"[NOT SUB] User {user_id} not in {channel_id} and mode != on") 66 | return False 67 | 68 | except Exception as e: 69 | print(f"[!] Error in is_sub(): {e}") 70 | return False 71 | 72 | 73 | async def encode(string): 74 | string_bytes = string.encode("ascii") 75 | base64_bytes = base64.urlsafe_b64encode(string_bytes) 76 | base64_string = (base64_bytes.decode("ascii")).strip("=") 77 | return base64_string 78 | 79 | async def decode(base64_string): 80 | base64_string = base64_string.strip("=") # links generated before this commit will be having = sign, hence striping them to handle padding errors. 81 | base64_bytes = (base64_string + "=" * (-len(base64_string) % 4)).encode("ascii") 82 | string_bytes = base64.urlsafe_b64decode(base64_bytes) 83 | string = string_bytes.decode("ascii") 84 | return string 85 | 86 | async def get_messages(client, message_ids): 87 | messages = [] 88 | total_messages = 0 89 | while total_messages != len(message_ids): 90 | temb_ids = message_ids[total_messages:total_messages+200] 91 | try: 92 | msgs = await client.get_messages( 93 | chat_id=client.db_channel.id, 94 | message_ids=temb_ids 95 | ) 96 | except FloodWait as e: 97 | await asyncio.sleep(e.x) 98 | msgs = await client.get_messages( 99 | chat_id=client.db_channel.id, 100 | message_ids=temb_ids 101 | ) 102 | except: 103 | pass 104 | total_messages += len(temb_ids) 105 | messages.extend(msgs) 106 | return messages 107 | 108 | async def get_message_id(client, message): 109 | if message.forward_from_chat: 110 | if message.forward_from_chat.id == client.db_channel.id: 111 | return message.forward_from_message_id 112 | else: 113 | return 0 114 | elif message.forward_sender_name: 115 | return 0 116 | elif message.text: 117 | pattern = "https://t.me/(?:c/)?(.*)/(\d+)" 118 | matches = re.match(pattern,message.text) 119 | if not matches: 120 | return 0 121 | channel_id = matches.group(1) 122 | msg_id = int(matches.group(2)) 123 | if channel_id.isdigit(): 124 | if f"-100{channel_id}" == str(client.db_channel.id): 125 | return msg_id 126 | else: 127 | if channel_id == client.db_channel.username: 128 | return msg_id 129 | else: 130 | return 0 131 | 132 | 133 | def get_readable_time(seconds: int) -> str: 134 | count = 0 135 | up_time = "" 136 | time_list = [] 137 | time_suffix_list = ["s", "m", "h", "days"] 138 | while count < 4: 139 | count += 1 140 | remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24) 141 | if seconds == 0 and remainder == 0: 142 | break 143 | time_list.append(int(result)) 144 | seconds = int(remainder) 145 | hmm = len(time_list) 146 | for x in range(hmm): 147 | time_list[x] = str(time_list[x]) + time_suffix_list[x] 148 | if len(time_list) == 4: 149 | up_time += f"{time_list.pop()}, " 150 | time_list.reverse() 151 | up_time += ":".join(time_list) 152 | return up_time 153 | 154 | 155 | def get_exp_time(seconds): 156 | periods = [('days', 86400), ('hours', 3600), ('mins', 60), ('secs', 1)] 157 | result = '' 158 | for period_name, period_seconds in periods: 159 | if seconds >= period_seconds: 160 | period_value, seconds = divmod(seconds, period_seconds) 161 | result += f'{int(period_value)} {period_name}' 162 | return result 163 | 164 | subscribed = filters.create(is_subscribed) 165 | admin = filters.create(check_admin) 166 | 167 | #rohit_1888 on Tg : -------------------------------------------------------------------------------- /heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | worker: Dockerfile 4 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from bot import Bot 2 | import pyrogram.utils 3 | 4 | pyrogram.utils.MIN_CHANNEL_ID = -1009147483647 5 | 6 | if __name__ == "__main__": 7 | Bot().run() 8 | -------------------------------------------------------------------------------- /plugins/__init__.py: -------------------------------------------------------------------------------- 1 | #(©)Codexbotz 2 | #@iryme 3 | 4 | 5 | 6 | 7 | 8 | from aiohttp import web 9 | from .route import routes 10 | 11 | 12 | async def web_server(): 13 | web_app = web.Application(client_max_size=30000000) 14 | web_app.add_routes(routes) 15 | return web_app 16 | -------------------------------------------------------------------------------- /plugins/admin.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import os 3 | import random 4 | import sys 5 | import time 6 | from pyrogram import Client, filters, __version__ 7 | from pyrogram.enums import ParseMode, ChatAction, ChatMemberStatus, ChatType 8 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery, ReplyKeyboardMarkup, ChatMemberUpdated, ChatPermissions 9 | from pyrogram.errors.exceptions.bad_request_400 import UserNotParticipant, InviteHashEmpty, ChatAdminRequired, PeerIdInvalid, UserIsBlocked, InputUserDeactivated 10 | from bot import Bot 11 | from config import * 12 | from helper_func import * 13 | from database.database import * 14 | 15 | 16 | 17 | # Commands for adding admins by owner 18 | @Bot.on_message(filters.command('add_admin') & filters.private & filters.user(OWNER_ID)) 19 | async def add_admins(client: Client, message: Message): 20 | pro = await message.reply("ᴘʟᴇᴀsᴇ ᴡᴀɪᴛ..", quote=True) 21 | check = 0 22 | admin_ids = await db.get_all_admins() 23 | admins = message.text.split()[1:] 24 | 25 | reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("ᴄʟᴏsᴇ", callback_data="close")]]) 26 | 27 | if not admins: 28 | return await pro.edit( 29 | "You need to provide user ID(s) to add as admin.\n\n" 30 | "Usage:\n" 31 | "
/add_admin [user_id]
— Add one or more user IDs\n\n"
32 | "Example:\n"
33 | "/add_admin 1234567890 9876543210
",
34 | reply_markup=reply_markup
35 | )
36 |
37 | admin_list = ""
38 | for id in admins:
39 | try:
40 | id = int(id)
41 | except:
42 | admin_list += f"Invalid ID: {id}
\n"
43 | continue
44 |
45 | if id in admin_ids:
46 | admin_list += f"ID {id}
already exists.
\n"
47 | continue
48 |
49 | id = str(id)
50 | if id.isdigit() and len(id) == 10:
51 | admin_list += f"(ID: {id}
) added.
\n"
52 | check += 1
53 | else:
54 | admin_list += f"Invalid ID: {id}
\n"
55 |
56 | if check == len(admins):
57 | for id in admins:
58 | await db.add_admin(int(id))
59 | await pro.edit(f"✅ Admin(s) added successfully:\n\n{admin_list}", reply_markup=reply_markup)
60 | else:
61 | await pro.edit(
62 | f"❌ Some errors occurred while adding admins:\n\n{admin_list.strip()}\n\n"
63 | "Please check and try again.",
64 | reply_markup=reply_markup
65 | )
66 |
67 |
68 | @Bot.on_message(filters.command('deladmin') & filters.private & filters.user(OWNER_ID))
69 | async def delete_admins(client: Client, message: Message):
70 | pro = await message.reply("ᴘʟᴇᴀsᴇ ᴡᴀɪᴛ..", quote=True)
71 | admin_ids = await db.get_all_admins()
72 | admins = message.text.split()[1:]
73 |
74 | reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("ᴄʟᴏsᴇ", callback_data="close")]])
75 |
76 | if not admins:
77 | return await pro.edit(
78 | "Please provide valid admin ID(s) to remove.\n\n"
79 | "Usage:\n"
80 | "/deladmin [user_id]
— Remove specific IDs\n"
81 | "/deladmin all
— Remove all admins",
82 | reply_markup=reply_markup
83 | )
84 |
85 | if len(admins) == 1 and admins[0].lower() == "all":
86 | if admin_ids:
87 | for id in admin_ids:
88 | await db.del_admin(id)
89 | ids = "\n".join(f"{admin}
✅
" for admin in admin_ids)
90 | return await pro.edit(f"⛔️ All admin IDs have been removed:\n{ids}", reply_markup=reply_markup)
91 | else:
92 | return await pro.edit("No admin IDs to remove.", reply_markup=reply_markup) 93 | 94 | if admin_ids: 95 | passed = '' 96 | for admin_id in admins: 97 | try: 98 | id = int(admin_id) 99 | except: 100 | passed += f"
Invalid ID: {admin_id}
\n"
101 | continue
102 |
103 | if id in admin_ids:
104 | await db.del_admin(id)
105 | passed += f"{id}
✅ Removed
\n"
106 | else:
107 | passed += f"ID {id}
not found in admin list.
\n"
108 |
109 | await pro.edit(f"⛔️ Admin removal result:\n\n{passed}", reply_markup=reply_markup)
110 | else:
111 | await pro.edit("No admin IDs available to delete.", reply_markup=reply_markup) 112 | 113 | 114 | @Bot.on_message(filters.command('admins') & filters.private & admin) 115 | async def get_admins(client: Client, message: Message): 116 | pro = await message.reply("ᴘʟᴇᴀsᴇ ᴡᴀɪᴛ..", quote=True) 117 | admin_ids = await db.get_all_admins() 118 | 119 | if not admin_ids: 120 | admin_list = "
❌ No admins found." 121 | else: 122 | admin_list = "\n".join(f"
ID: {id}
" for id in admin_ids)
123 |
124 | reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("ᴄʟᴏsᴇ", callback_data="close")]])
125 | await pro.edit(f"⚡ Current Admin List:\n\n{admin_list}", reply_markup=reply_markup)
126 |
--------------------------------------------------------------------------------
/plugins/banuser.py:
--------------------------------------------------------------------------------
1 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888
2 | # Ask Doubt on telegram @CodeflixSupport
3 | #
4 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >.
5 | #
6 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project,
7 | # and is released under the MIT License.
8 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE >
9 | #
10 | # All rights reserved.
11 | #
12 |
13 | import asyncio
14 | import os
15 | import random
16 | import sys
17 | import time
18 | from datetime import datetime, timedelta
19 | from pyrogram import Client, filters, __version__
20 | from pyrogram.enums import ParseMode, ChatAction
21 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery, ReplyKeyboardMarkup, ChatInviteLink, ChatPrivileges
22 | from pyrogram.errors.exceptions.bad_request_400 import UserNotParticipant
23 | from pyrogram.errors import FloodWait, UserIsBlocked, InputUserDeactivated, UserNotParticipant
24 | from bot import Bot
25 | from config import *
26 | from helper_func import *
27 | from database.database import *
28 |
29 |
30 |
31 | #BAN-USER-SYSTEM
32 | @Bot.on_message(filters.private & filters.command('ban') & admin)
33 | async def add_banuser(client: Client, message: Message):
34 | pro = await message.reply("⏳ Pʀᴏᴄᴇssɪɴɢ ʀᴇǫᴜᴇsᴛ...", quote=True)
35 | banuser_ids = await db.get_ban_users()
36 | banusers = message.text.split()[1:]
37 |
38 | reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("❌ Cʟᴏsᴇ", callback_data="close")]])
39 |
40 | if not banusers:
41 | return await pro.edit(
42 | "❗ Yᴏᴜ ᴍᴜsᴛ ᴘʀᴏᴠɪᴅᴇ ᴜsᴇʀ IDs ᴛᴏ ʙᴀɴ.\n\n"
43 | "📌 Usᴀɢᴇ:\n"
44 | "/ban [user_id]
— Ban one or more users by ID.",
45 | reply_markup=reply_markup
46 | )
47 |
48 | report, success_count = "", 0
49 | for uid in banusers:
50 | try:
51 | uid_int = int(uid)
52 | except:
53 | report += f"⚠️ Iɴᴠᴀʟɪᴅ ID: {uid}
\n"
54 | continue
55 |
56 | if uid_int in await db.get_all_admins() or uid_int == OWNER_ID:
57 | report += f"⛔ Sᴋɪᴘᴘᴇᴅ ᴀᴅᴍɪɴ/ᴏᴡɴᴇʀ ID: {uid_int}
\n"
58 | continue
59 |
60 | if uid_int in banuser_ids:
61 | report += f"⚠️ Aʟʀᴇᴀᴅʏ : {uid_int}
\n"
62 | continue
63 |
64 | if len(str(uid_int)) == 10:
65 | await db.add_ban_user(uid_int)
66 | report += f"✅ Bᴀɴɴᴇᴅ: {uid_int}
\n"
67 | success_count += 1
68 | else:
69 | report += f"⚠️ Invalid Telegram ID length: {uid_int}
\n"
70 |
71 | if success_count:
72 | await pro.edit(f"✅ Bᴀɴɴᴇᴅ Usᴇʀs Uᴘᴅᴀᴛᴇᴅ:\n\n{report}", reply_markup=reply_markup)
73 | else:
74 | await pro.edit(f"❌ Nᴏ ᴜsᴇʀs ᴡᴇʀᴇ ʙᴀɴɴᴇᴅ.\n\n{report}", reply_markup=reply_markup)
75 |
76 | @Bot.on_message(filters.private & filters.command('unban') & admin)
77 | async def delete_banuser(client: Client, message: Message):
78 | pro = await message.reply("⏳ Pʀᴏᴄᴇssɪɴɢ ʀᴇǫᴜᴇsᴛ...", quote=True)
79 | banuser_ids = await db.get_ban_users()
80 | banusers = message.text.split()[1:]
81 |
82 | reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("❌ Cʟᴏsᴇ", callback_data="close")]])
83 |
84 | if not banusers:
85 | return await pro.edit(
86 | "❗ Pʟᴇᴀsᴇ ᴘʀᴏᴠɪᴅᴇ ᴜsᴇʀ IDs ᴛᴏ ᴜɴʙᴀɴ.\n\n"
87 | "📌 Usage:\n"
88 | "/unban [user_id]
— Unban specific user(s)\n"
89 | "/unban all
— Remove all banned users",
90 | reply_markup=reply_markup
91 | )
92 |
93 | if banusers[0].lower() == "all":
94 | if not banuser_ids:
95 | return await pro.edit("✅ NO ᴜsᴇʀs ɪɴ ᴛʜᴇ ʙᴀɴ ʟɪsᴛ.", reply_markup=reply_markup)
96 | for uid in banuser_ids:
97 | await db.del_ban_user(uid)
98 | listed = "\n".join([f"✅ Uɴʙᴀɴɴᴇᴅ: {uid}
" for uid in banuser_ids])
99 | return await pro.edit(f"🚫 Cʟᴇᴀʀᴇᴅ Bᴀɴ Lɪsᴛ:\n\n{listed}", reply_markup=reply_markup)
100 |
101 | report = ""
102 | for uid in banusers:
103 | try:
104 | uid_int = int(uid)
105 | except:
106 | report += f"⚠️ Iɴᴀᴠʟɪᴅ ID: {uid}
\n"
107 | continue
108 |
109 | if uid_int in banuser_ids:
110 | await db.del_ban_user(uid_int)
111 | report += f"✅ Uɴʙᴀɴɴᴇᴅ: {uid_int}
\n"
112 | else:
113 | report += f"⚠️ Nᴏᴛ ɪɴ ʙᴀɴ ʟɪsᴛ: {uid_int}
\n"
114 |
115 | await pro.edit(f"🚫 Uɴʙᴀɴ Rᴇᴘᴏʀᴛ:\n\n{report}", reply_markup=reply_markup)
116 |
117 | @Bot.on_message(filters.private & filters.command('banlist') & admin)
118 | async def get_banuser_list(client: Client, message: Message):
119 | pro = await message.reply("⏳ Fᴇᴛᴄʜɪɴɢ Bᴀɴ Lɪsᴛ...", quote=True)
120 | banuser_ids = await db.get_ban_users()
121 |
122 | if not banuser_ids:
123 | return await pro.edit("✅ NO ᴜsᴇʀs ɪɴ ᴛʜᴇ ʙᴀɴ Lɪsᴛ.", reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("❌ Cʟᴏsᴇ", callback_data="close")]]))
124 |
125 | result = "🚫 Bᴀɴɴᴇᴅ Usᴇʀs:\n\n"
126 | for uid in banuser_ids:
127 | await message.reply_chat_action(ChatAction.TYPING)
128 | try:
129 | user = await client.get_users(uid)
130 | user_link = f'{user.first_name}'
131 | result += f"• {user_link} — {uid}
\n"
132 | except:
133 | result += f"• {uid}
— Could not fetch name\n"
134 |
135 | await pro.edit(result, disable_web_page_preview=True, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("❌ Cʟᴏsᴇ", callback_data="close")]]))
136 |
--------------------------------------------------------------------------------
/plugins/broadcast.py:
--------------------------------------------------------------------------------
1 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888
2 | # Ask Doubt on telegram @CodeflixSupport
3 | #
4 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >.
5 | #
6 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project,
7 | # and is released under the MIT License.
8 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE >
9 | #
10 | # All rights reserved.
11 | #
12 |
13 | import asyncio
14 | import os
15 | import random
16 | import sys
17 | import time
18 | from datetime import datetime, timedelta
19 | from pyrogram import Client, filters, __version__
20 | from pyrogram.enums import ParseMode, ChatAction
21 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery, ReplyKeyboardMarkup, ChatInviteLink, ChatPrivileges
22 | from pyrogram.errors.exceptions.bad_request_400 import UserNotParticipant
23 | from pyrogram.errors import FloodWait, UserIsBlocked, InputUserDeactivated, UserNotParticipant
24 | from bot import Bot
25 | from config import *
26 | from helper_func import *
27 | from database.database import *
28 |
29 |
30 | #=====================================================================================##
31 |
32 | REPLY_ERROR = "Use this command as a reply to any telegram message without any spaces.
"
33 |
34 | #=====================================================================================##
35 |
36 |
37 | @Bot.on_message(filters.private & filters.command('pbroadcast') & admin)
38 | async def send_pin_text(client: Bot, message: Message):
39 | if message.reply_to_message:
40 | query = await db.full_userbase()
41 | broadcast_msg = message.reply_to_message
42 | total = 0
43 | successful = 0
44 | blocked = 0
45 | deleted = 0
46 | unsuccessful = 0
47 |
48 | pls_wait = await message.reply("ʙʀᴏᴀᴅᴄᴀꜱᴛ ᴘʀᴏᴄᴇꜱꜱɪɴɢ....")
49 | for chat_id in query:
50 | try:
51 | # Send and pin the message
52 | sent_msg = await broadcast_msg.copy(chat_id)
53 | await client.pin_chat_message(chat_id=chat_id, message_id=sent_msg.id, both_sides=True)
54 | successful += 1
55 | except FloodWait as e:
56 | await asyncio.sleep(e.x)
57 | sent_msg = await broadcast_msg.copy(chat_id)
58 | await client.pin_chat_message(chat_id=chat_id, message_id=sent_msg.id, both_sides=True)
59 | successful += 1
60 | except UserIsBlocked:
61 | await db.del_user(chat_id)
62 | blocked += 1
63 | except InputUserDeactivated:
64 | await db.del_user(chat_id)
65 | deleted += 1
66 | except Exception as e:
67 | print(f"Failed to send or pin message to {chat_id}: {e}")
68 | unsuccessful += 1
69 | total += 1
70 |
71 | status = f"""ʙʀᴏᴀᴅᴄᴀꜱᴛ ᴄᴏᴍᴘʟᴇᴛᴇᴅ
72 |
73 | Total Users: {total}
74 | Successful: {successful}
75 | Blocked Users: {blocked}
76 | Deleted Accounts: {deleted}
77 | Unsuccessful: {unsuccessful}
"""
78 |
79 | return await pls_wait.edit(status)
80 |
81 | else:
82 | msg = await message.reply("Reply to a message to broadcast and pin it.")
83 | await asyncio.sleep(8)
84 | await msg.delete()
85 |
86 | #=====================================================================================##
87 |
88 |
89 | @Bot.on_message(filters.private & filters.command('broadcast') & admin)
90 | async def send_text(client: Bot, message: Message):
91 | if message.reply_to_message:
92 | query = await db.full_userbase()
93 | broadcast_msg = message.reply_to_message
94 | total = 0
95 | successful = 0
96 | blocked = 0
97 | deleted = 0
98 | unsuccessful = 0
99 |
100 | pls_wait = await message.reply("ʙʀᴏᴀᴅᴄᴀꜱᴛ ᴘʀᴏᴄᴇꜱꜱɪɴɢ....")
101 | for chat_id in query:
102 | try:
103 | await broadcast_msg.copy(chat_id)
104 | successful += 1
105 | except FloodWait as e:
106 | await asyncio.sleep(e.x)
107 | await broadcast_msg.copy(chat_id)
108 | successful += 1
109 | except UserIsBlocked:
110 | await db.del_user(chat_id)
111 | blocked += 1
112 | except InputUserDeactivated:
113 | await db.del_user(chat_id)
114 | deleted += 1
115 | except:
116 | unsuccessful += 1
117 | pass
118 | total += 1
119 |
120 | status = f"""ʙʀᴏᴀᴅᴄᴀꜱᴛ...
121 |
122 | Total Users: {total}
123 | Successful: {successful}
124 | Blocked Users: {blocked}
125 | Deleted Accounts: {deleted}
126 | Unsuccessful: {unsuccessful}
"""
127 |
128 | return await pls_wait.edit(status)
129 |
130 | else:
131 | msg = await message.reply(REPLY_ERROR)
132 | await asyncio.sleep(8)
133 | await msg.delete()
134 |
135 | #=====================================================================================##
136 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888
137 | # Ask Doubt on telegram @CodeflixSupport
138 | #
139 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >.
140 | #
141 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project,
142 | # and is released under the MIT License.
143 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE >
144 | #
145 | # All rights reserved.
146 | #
147 |
148 | # broadcast with auto-del
149 |
150 | @Bot.on_message(filters.private & filters.command('dbroadcast') & admin)
151 | async def delete_broadcast(client: Bot, message: Message):
152 | if message.reply_to_message:
153 | try:
154 | duration = int(message.command[1]) # Get the duration in seconds
155 | except (IndexError, ValueError):
156 | await message.reply("Pʟᴇᴀsᴇ ᴜsᴇ ᴀ ᴠᴀʟɪᴅ ᴅᴜʀᴀᴛɪᴏɴ ɪɴ sᴇᴄᴏɴᴅs. Usᴀɢᴇ: /dbroadcast {duration}")
157 | return
158 |
159 | query = await db.full_userbase()
160 | broadcast_msg = message.reply_to_message
161 | total = 0
162 | successful = 0
163 | blocked = 0
164 | deleted = 0
165 | unsuccessful = 0
166 |
167 | pls_wait = await message.reply("Broadcast with auto-delete processing....")
168 | for chat_id in query:
169 | try:
170 | sent_msg = await broadcast_msg.copy(chat_id)
171 | await asyncio.sleep(duration) # Wait for the specified duration
172 | await sent_msg.delete() # Delete the message after the duration
173 | successful += 1
174 | except FloodWait as e:
175 | await asyncio.sleep(e.x)
176 | sent_msg = await broadcast_msg.copy(chat_id)
177 | await asyncio.sleep(duration)
178 | await sent_msg.delete()
179 | successful += 1
180 | except UserIsBlocked:
181 | await db.del_user(chat_id)
182 | blocked += 1
183 | except InputUserDeactivated:
184 | await db.del_user(chat_id)
185 | deleted += 1
186 | except:
187 | unsuccessful += 1
188 | pass
189 | total += 1
190 |
191 | status = f"""Bʀᴏᴀᴅᴄᴀsᴛɪɴɢ ᴡɪᴛʜ Aᴜᴛᴏ-Dᴇʟᴇᴛᴇ...
192 |
193 | Total Users: {total}
194 | Successful: {successful}
195 | Blocked Users: {blocked}
196 | Deleted Accounts: {deleted}
197 | Unsuccessful: {unsuccessful}
"""
198 |
199 | return await pls_wait.edit(status)
200 |
201 | else:
202 | msg = await message.reply("Pʟᴇᴀsᴇ ʀᴇᴘʟʏ ᴛᴏ ᴀ ᴍᴇssᴀɢᴇ ᴛᴏ ʙʀᴏᴀᴅᴄᴀsᴛ ɪᴛ ᴡɪᴛʜ Aᴜᴛᴏ-Dᴇʟᴇᴛᴇ.")
203 | await asyncio.sleep(8)
204 | await msg.delete()
205 |
206 |
207 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888
208 | # Ask Doubt on telegram @CodeflixSupport
209 | #
210 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >.
211 | #
212 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project,
213 | # and is released under the MIT License.
214 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE >
215 | #
216 | # All rights reserved.
217 | #
--------------------------------------------------------------------------------
/plugins/cbb.py:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >.
3 | #
4 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project,
5 | # and is released under the MIT License.
6 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE >
7 | #
8 | # All rights reserved.
9 |
10 | from pyrogram import Client
11 | from bot import Bot
12 | from config import *
13 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
14 | from database.database import *
15 |
16 | @Bot.on_callback_query()
17 | async def cb_handler(client: Bot, query: CallbackQuery):
18 | data = query.data
19 |
20 | if data == "help":
21 | await query.message.edit_text(
22 | text=HELP_TXT.format(first=query.from_user.first_name),
23 | disable_web_page_preview=True,
24 | reply_markup=InlineKeyboardMarkup([
25 | [InlineKeyboardButton('ʜᴏᴍᴇ', callback_data='start'),
26 | InlineKeyboardButton("ᴄʟᴏꜱᴇ", callback_data='close')]
27 | ])
28 | )
29 |
30 | elif data == "about":
31 | await query.message.edit_text(
32 | text=ABOUT_TXT.format(first=query.from_user.first_name),
33 | disable_web_page_preview=True,
34 | reply_markup=InlineKeyboardMarkup([
35 | [InlineKeyboardButton('ʜᴏᴍᴇ', callback_data='start'),
36 | InlineKeyboardButton('ᴄʟᴏꜱᴇ', callback_data='close')]
37 | ])
38 | )
39 |
40 | elif data == "start":
41 | await query.message.edit_text(
42 | text=START_MSG.format(first=query.from_user.first_name),
43 | disable_web_page_preview=True,
44 | reply_markup=InlineKeyboardMarkup([
45 | [InlineKeyboardButton("ʜᴇʟᴘ", callback_data='help'),
46 | InlineKeyboardButton("ᴀʙᴏᴜᴛ", callback_data='about')]
47 | ])
48 | )
49 |
50 | elif data == "close":
51 | await query.message.delete()
52 | try:
53 | await query.message.reply_to_message.delete()
54 | except:
55 | pass
56 |
57 | elif data.startswith("rfs_ch_"):
58 | cid = int(data.split("_")[2])
59 | try:
60 | chat = await client.get_chat(cid)
61 | mode = await db.get_channel_mode(cid)
62 | status = "🟢 ᴏɴ" if mode == "on" else "🔴 ᴏғғ"
63 | new_mode = "ᴏғғ" if mode == "on" else "on"
64 | buttons = [
65 | [InlineKeyboardButton(f"ʀᴇǫ ᴍᴏᴅᴇ {'OFF' if mode == 'on' else 'ON'}", callback_data=f"rfs_toggle_{cid}_{new_mode}")],
66 | [InlineKeyboardButton("‹ ʙᴀᴄᴋ", callback_data="fsub_back")]
67 | ]
68 | await query.message.edit_text(
69 | f"Channel: {chat.title}\nCurrent Force-Sub Mode: {status}",
70 | reply_markup=InlineKeyboardMarkup(buttons)
71 | )
72 | except Exception:
73 | await query.answer("Failed to fetch channel info", show_alert=True)
74 |
75 | elif data.startswith("rfs_toggle_"):
76 | cid, action = data.split("_")[2:]
77 | cid = int(cid)
78 | mode = "on" if action == "on" else "off"
79 |
80 | await db.set_channel_mode(cid, mode)
81 | await query.answer(f"Force-Sub set to {'ON' if mode == 'on' else 'OFF'}")
82 |
83 | # Refresh the same channel's mode view
84 | chat = await client.get_chat(cid)
85 | status = "🟢 ON" if mode == "on" else "🔴 OFF"
86 | new_mode = "off" if mode == "on" else "on"
87 | buttons = [
88 | [InlineKeyboardButton(f"ʀᴇǫ ᴍᴏᴅᴇ {'OFF' if mode == 'on' else 'ON'}", callback_data=f"rfs_toggle_{cid}_{new_mode}")],
89 | [InlineKeyboardButton("‹ ʙᴀᴄᴋ", callback_data="fsub_back")]
90 | ]
91 | await query.message.edit_text(
92 | f"Channel: {chat.title}\nCurrent Force-Sub Mode: {status}",
93 | reply_markup=InlineKeyboardMarkup(buttons)
94 | )
95 |
96 | elif data == "fsub_back":
97 | channels = await db.show_channels()
98 | buttons = []
99 | for cid in channels:
100 | try:
101 | chat = await client.get_chat(cid)
102 | mode = await db.get_channel_mode(cid)
103 | status = "🟢" if mode == "on" else "🔴"
104 | buttons.append([InlineKeyboardButton(f"{status} {chat.title}", callback_data=f"rfs_ch_{cid}")])
105 | except:
106 | continue
107 |
108 | await query.message.edit_text(
109 | "sᴇʟᴇᴄᴛ ᴀ ᴄʜᴀɴɴᴇʟ ᴛᴏ ᴛᴏɢɢʟᴇ ɪᴛs ғᴏʀᴄᴇ-sᴜʙ ᴍᴏᴅᴇ:",
110 | reply_markup=InlineKeyboardMarkup(buttons)
111 | )
112 |
--------------------------------------------------------------------------------
/plugins/channel_post.py:
--------------------------------------------------------------------------------
1 | #(©)Codexbotz
2 |
3 | import asyncio
4 | from pyrogram import filters, Client
5 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton
6 | from pyrogram.errors import FloodWait
7 |
8 | from bot import Bot
9 | from config import *
10 | from helper_func import encode, admin
11 |
12 | @Bot.on_message(filters.private & admin & ~filters.command(['start', 'commands','users','broadcast','batch', 'custom_batch', 'genlink','stats', 'dlt_time', 'check_dlt_time', 'dbroadcast', 'ban', 'unban', 'banlist', 'addchnl', 'delchnl', 'listchnl', 'fsub_mode', 'pbroadcast', 'add_admin', 'deladmin', 'admins']))
13 | async def channel_post(client: Client, message: Message):
14 | reply_text = await message.reply_text("Please Wait...!", quote = True)
15 | try:
16 | post_message = await message.copy(chat_id = client.db_channel.id, disable_notification=True)
17 | except FloodWait as e:
18 | await asyncio.sleep(e.x)
19 | post_message = await message.copy(chat_id = client.db_channel.id, disable_notification=True)
20 | except Exception as e:
21 | print(e)
22 | await reply_text.edit_text("Something went Wrong..!")
23 | return
24 | converted_id = post_message.id * abs(client.db_channel.id)
25 | string = f"get-{converted_id}"
26 | base64_string = await encode(string)
27 | link = f"https://t.me/{client.username}?start={base64_string}"
28 |
29 | reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("🔁 Share URL", url=f'https://telegram.me/share/url?url={link}')]])
30 |
31 | await reply_text.edit(f"Here is your link\n\n{link}", reply_markup=reply_markup, disable_web_page_preview = True)
32 |
33 | if not DISABLE_CHANNEL_BUTTON:
34 | await post_message.edit_reply_markup(reply_markup)
35 |
--------------------------------------------------------------------------------
/plugins/link_generator.py:
--------------------------------------------------------------------------------
1 | #(©)Codexbotz
2 |
3 | from pyrogram import Client, filters
4 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton
5 | from bot import Bot
6 | from pyrogram.types import ReplyKeyboardMarkup, ReplyKeyboardRemove
7 | from asyncio import TimeoutError
8 | from helper_func import encode, get_message_id, admin
9 |
10 | @Bot.on_message(filters.private & admin & filters.command('batch'))
11 | async def batch(client: Client, message: Message):
12 | while True:
13 | try:
14 | first_message = await client.ask(text = "Forward the First Message from DB Channel (with Quotes)..\n\nor Send the DB Channel Post Link", chat_id = message.from_user.id, filters=(filters.forwarded | (filters.text & ~filters.forwarded)), timeout=60)
15 | except:
16 | return
17 | f_msg_id = await get_message_id(client, first_message)
18 | if f_msg_id:
19 | break
20 | else:
21 | await first_message.reply("❌ Error\n\nthis Forwarded Post is not from my DB Channel or this Link is taken from DB Channel", quote = True)
22 | continue
23 |
24 | while True:
25 | try:
26 | second_message = await client.ask(text = "Forward the Last Message from DB Channel (with Quotes)..\nor Send the DB Channel Post link", chat_id = message.from_user.id, filters=(filters.forwarded | (filters.text & ~filters.forwarded)), timeout=60)
27 | except:
28 | return
29 | s_msg_id = await get_message_id(client, second_message)
30 | if s_msg_id:
31 | break
32 | else:
33 | await second_message.reply("❌ Error\n\nthis Forwarded Post is not from my DB Channel or this Link is taken from DB Channel", quote = True)
34 | continue
35 |
36 |
37 | string = f"get-{f_msg_id * abs(client.db_channel.id)}-{s_msg_id * abs(client.db_channel.id)}"
38 | base64_string = await encode(string)
39 | link = f"https://t.me/{client.username}?start={base64_string}"
40 | reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("🔁 Share URL", url=f'https://telegram.me/share/url?url={link}')]])
41 | await second_message.reply_text(f"Here is your link\n\n{link}", quote=True, reply_markup=reply_markup)
42 |
43 |
44 | @Bot.on_message(filters.private & admin & filters.command('genlink'))
45 | async def link_generator(client: Client, message: Message):
46 | while True:
47 | try:
48 | channel_message = await client.ask(text = "Forward Message from the DB Channel (with Quotes)..\nor Send the DB Channel Post link", chat_id = message.from_user.id, filters=(filters.forwarded | (filters.text & ~filters.forwarded)), timeout=60)
49 | except:
50 | return
51 | msg_id = await get_message_id(client, channel_message)
52 | if msg_id:
53 | break
54 | else:
55 | await channel_message.reply("❌ Error\n\nthis Forwarded Post is not from my DB Channel or this Link is not taken from DB Channel", quote = True)
56 | continue
57 |
58 | base64_string = await encode(f"get-{msg_id * abs(client.db_channel.id)}")
59 | link = f"https://t.me/{client.username}?start={base64_string}"
60 | reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("🔁 Share URL", url=f'https://telegram.me/share/url?url={link}')]])
61 | await channel_message.reply_text(f"Here is your link\n\n{link}", quote=True, reply_markup=reply_markup)
62 |
63 |
64 | @Bot.on_message(filters.private & admin & filters.command("custom_batch"))
65 | async def custom_batch(client: Client, message: Message):
66 | collected = []
67 | STOP_KEYBOARD = ReplyKeyboardMarkup([["STOP"]], resize_keyboard=True)
68 |
69 | await message.reply("Send all messages you want to include in batch.\n\nPress STOP when you're done.", reply_markup=STOP_KEYBOARD)
70 |
71 | while True:
72 | try:
73 | user_msg = await client.ask(
74 | chat_id=message.chat.id,
75 | text="Waiting for files/messages...\nPress STOP to finish.",
76 | timeout=60
77 | )
78 | except asyncio.TimeoutError:
79 | break
80 |
81 | if user_msg.text and user_msg.text.strip().upper() == "STOP":
82 | break
83 |
84 | try:
85 | sent = await user_msg.copy(client.db_channel.id, disable_notification=True)
86 | collected.append(sent.id)
87 | except Exception as e:
88 | await message.reply(f"❌ Failed to store a message:\n{e}
")
89 | continue
90 |
91 | await message.reply("✅ Batch collection complete.", reply_markup=ReplyKeyboardRemove())
92 |
93 | if not collected:
94 | await message.reply("❌ No messages were added to batch.")
95 | return
96 |
97 | start_id = collected[0] * abs(client.db_channel.id)
98 | end_id = collected[-1] * abs(client.db_channel.id)
99 | string = f"get-{start_id}-{end_id}"
100 | base64_string = await encode(string)
101 | link = f"https://t.me/{client.username}?start={base64_string}"
102 |
103 | reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("🔁 Share URL", url=f'https://telegram.me/share/url?url={link}')]])
104 | await message.reply(f"Here is your custom batch link:\n\n{link}", reply_markup=reply_markup)
--------------------------------------------------------------------------------
/plugins/request_fsub.py:
--------------------------------------------------------------------------------
1 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888
2 | # Ask Doubt on telegram @CodeflixSupport
3 | #
4 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >.
5 | #
6 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project,
7 | # and is released under the MIT License.
8 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE >
9 | #
10 | # All rights reserved.
11 | #
12 | import asyncio
13 | import os
14 | import random
15 | import sys
16 | import time
17 | from pyrogram import Client, filters, __version__
18 | from pyrogram.enums import ParseMode, ChatAction, ChatMemberStatus, ChatType
19 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery, ReplyKeyboardMarkup, ChatMemberUpdated, ChatPermissions
20 | from pyrogram.errors.exceptions.bad_request_400 import UserNotParticipant, InviteHashEmpty, ChatAdminRequired, PeerIdInvalid, UserIsBlocked, InputUserDeactivated, UserNotParticipant
21 | from bot import Bot
22 | from config import *
23 | from helper_func import *
24 | from database.database import *
25 |
26 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888
27 | # Ask Doubt on telegram @CodeflixSupport
28 | #
29 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >.
30 | #
31 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project,
32 | # and is released under the MIT License.
33 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE >
34 | #
35 | # All rights reserved.
36 | #
37 |
38 | #Request force sub mode commad,,,,,,
39 | @Bot.on_message(filters.command('fsub_mode') & filters.private & admin)
40 | async def change_force_sub_mode(client: Client, message: Message):
41 | temp = await message.reply("ᴡᴀɪᴛ ᴀ sᴇᴄ..", quote=True)
42 | channels = await db.show_channels()
43 |
44 | if not channels:
45 | return await temp.edit("❌ No force-sub channels found.")
46 |
47 | buttons = []
48 | for ch_id in channels:
49 | try:
50 | chat = await client.get_chat(ch_id)
51 | mode = await db.get_channel_mode(ch_id)
52 | status = "🟢" if mode == "on" else "🔴"
53 | title = f"{status} {chat.title}"
54 | buttons.append([InlineKeyboardButton(title, callback_data=f"rfs_ch_{ch_id}")])
55 | except:
56 | buttons.append([InlineKeyboardButton(f"⚠️ {ch_id} (Unavailable)", callback_data=f"rfs_ch_{ch_id}")])
57 |
58 | buttons.append([InlineKeyboardButton("Close ✖️", callback_data="close")])
59 |
60 | await temp.edit(
61 | "⚡ Select a channel to toggle Force-Sub Mode:",
62 | reply_markup=InlineKeyboardMarkup(buttons),
63 | disable_web_page_preview=True
64 | )
65 |
66 | # This handler captures membership updates (like when a user leaves, banned)
67 | @Bot.on_chat_member_updated()
68 | async def handle_Chatmembers(client, chat_member_updated: ChatMemberUpdated):
69 | chat_id = chat_member_updated.chat.id
70 |
71 | if await db.reqChannel_exist(chat_id):
72 | old_member = chat_member_updated.old_chat_member
73 |
74 | if not old_member:
75 | return
76 |
77 | if old_member.status == ChatMemberStatus.MEMBER:
78 | user_id = old_member.user.id
79 |
80 | if await db.req_user_exist(chat_id, user_id):
81 | await db.del_req_user(chat_id, user_id)
82 |
83 |
84 | # This handler will capture any join request to the channel/group where the bot is an admin
85 | @Bot.on_chat_join_request()
86 | async def handle_join_request(client, chat_join_request):
87 | chat_id = chat_join_request.chat.id
88 | user_id = chat_join_request.from_user.id
89 |
90 | #print(f"[JOIN REQUEST] User {user_id} sent join request to {chat_id}")
91 |
92 | # Print the result of db.reqChannel_exist to check if the channel exists
93 | channel_exists = await db.reqChannel_exist(chat_id)
94 | #print(f"Channel {chat_id} exists in the database: {channel_exists}")
95 |
96 | if channel_exists:
97 | if not await db.req_user_exist(chat_id, user_id):
98 | await db.req_user(chat_id, user_id)
99 | #print(f"Added user {user_id} to request list for {chat_id}")
100 |
101 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888
102 | # Ask Doubt on telegram @CodeflixSupport
103 | #
104 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >.
105 | #
106 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project,
107 | # and is released under the MIT License.
108 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE >
109 | #
110 | # All rights reserved.
111 | #
112 |
113 | # Add channel
114 | @Bot.on_message(filters.command('addchnl') & filters.private & admin)
115 | async def add_force_sub(client: Client, message: Message):
116 | temp = await message.reply("Wait a sec...", quote=True)
117 | args = message.text.split(maxsplit=1)
118 |
119 | if len(args) != 2:
120 | return await temp.edit(
121 | "Usage:\n/addchnl -100xxxxxxxxxx
"
122 | )
123 |
124 | try:
125 | chat_id = int(args[1])
126 | except ValueError:
127 | return await temp.edit("❌ Invalid chat ID!")
128 |
129 | all_chats = await db.show_channels()
130 | if chat_id in [c if isinstance(c, int) else c[0] for c in all_chats]:
131 | return await temp.edit(f"Already exists:\n{chat_id}
")
132 |
133 | try:
134 | chat = await client.get_chat(chat_id)
135 | if chat.type not in [ChatType.CHANNEL, ChatType.SUPERGROUP]:
136 | return await temp.edit("❌ Only channels/supergroups allowed.")
137 |
138 | bot_member = await client.get_chat_member(chat.id, "me")
139 | if bot_member.status not in [ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER]:
140 | return await temp.edit("❌ Bot must be admin in that chat.")
141 |
142 | # Try to get invite link
143 | try:
144 | link = await client.export_chat_invite_link(chat.id)
145 | except Exception:
146 | link = f"https://t.me/{chat.username}" if chat.username else f"https://t.me/c/{str(chat.id)[4:]}"
147 |
148 | await db.add_channel(chat_id)
149 | return await temp.edit(
150 | f"✅ Added Successfully!\n\n"
151 | f"Name: {chat.title}\n"
152 | f"ID: {chat_id}
",
153 | disable_web_page_preview=True
154 | )
155 |
156 | except Exception as e:
157 | return await temp.edit(f"❌ Failed to add chat:\n{chat_id}
\n\n{e}")
158 |
159 |
160 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888
161 | # Ask Doubt on telegram @CodeflixSupport
162 | #
163 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >.
164 | #
165 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project,
166 | # and is released under the MIT License.
167 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE >
168 | #
169 | # All rights reserved.
170 | #
171 |
172 | # Delete channel
173 | @Bot.on_message(filters.command('delchnl') & filters.private & admin)
174 | async def del_force_sub(client: Client, message: Message):
175 | temp = await message.reply("ᴡᴀɪᴛ ᴀ sᴇᴄ..", quote=True)
176 | args = message.text.split(maxsplit=1)
177 | all_channels = await db.show_channels()
178 |
179 | if len(args) != 2:
180 | return await temp.edit("Usage: /delchnl
")
181 |
182 | if args[1].lower() == "all":
183 | if not all_channels:
184 | return await temp.edit("❌ No force-sub channels found.")
185 | for ch_id in all_channels:
186 | await db.del_channel(ch_id)
187 | return await temp.edit("✅ All force-sub channels have been removed.")
188 |
189 | try:
190 | ch_id = int(args[1])
191 | except ValueError:
192 | return await temp.edit("❌ Invalid Channel ID")
193 |
194 | if ch_id in all_channels:
195 | await db.rem_channel(ch_id)
196 | return await temp.edit(f"✅ Channel removed: {ch_id}
")
197 | else:
198 | return await temp.edit(f"❌ Channel not found in force-sub list: {ch_id}
")
199 |
200 | # View all channels
201 | @Bot.on_message(filters.command('listchnl') & filters.private & admin)
202 | async def list_force_sub_channels(client: Client, message: Message):
203 | temp = await message.reply("ᴡᴀɪᴛ ᴀ sᴇᴄ..", quote=True)
204 | channels = await db.show_channels()
205 |
206 | if not channels:
207 | return await temp.edit("❌ No force-sub channels found.")
208 |
209 | result = "⚡ Force-sub Channels:\n\n"
210 | for ch_id in channels:
211 | try:
212 | chat = await client.get_chat(ch_id)
213 | link = chat.invite_link or await client.export_chat_invite_link(chat.id)
214 | result += f"• {chat.title} [{ch_id}
]\n"
215 | except Exception:
216 | result += f"• {ch_id}
— Unavailable\n"
217 |
218 | await temp.edit(result, disable_web_page_preview=True, reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("Close ✖️", callback_data="close")]]))
219 |
220 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888
221 | # Ask Doubt on telegram @CodeflixSupport
222 | #
223 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >.
224 | #
225 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project,
226 | # and is released under the MIT License.
227 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE >
228 | #
229 | # All rights reserved.
230 | #
231 |
--------------------------------------------------------------------------------
/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("Codeflix FileStore")
8 |
--------------------------------------------------------------------------------
/plugins/start.py:
--------------------------------------------------------------------------------
1 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888
2 | # Ask Doubt on telegram @CodeflixSupport
3 | #
4 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >.
5 | #
6 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project,
7 | # and is released under the MIT License.
8 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE >
9 | #
10 | # All rights reserved.
11 | #
12 |
13 | import asyncio
14 | import os
15 | import random
16 | import sys
17 | import time
18 | from datetime import datetime, timedelta
19 | from pyrogram import Client, filters, __version__
20 | from pyrogram.enums import ParseMode, ChatAction
21 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery, ReplyKeyboardMarkup, ChatInviteLink, ChatPrivileges
22 | from pyrogram.errors.exceptions.bad_request_400 import UserNotParticipant
23 | from pyrogram.errors import FloodWait, UserIsBlocked, InputUserDeactivated, UserNotParticipant
24 | from bot import Bot
25 | from config import *
26 | from helper_func import *
27 | from database.database import *
28 |
29 | BAN_SUPPORT = f"{BAN_SUPPORT}"
30 |
31 | @Bot.on_message(filters.command('start') & filters.private)
32 | async def start_command(client: Client, message: Message):
33 | user_id = message.from_user.id
34 |
35 | # Check if user is banned
36 | banned_users = await db.get_ban_users()
37 | if user_id in banned_users:
38 | return await message.reply_text(
39 | "⛔️ You are Bᴀɴɴᴇᴅ from using this bot.\n\n"
40 | "Contact support if you think this is a mistake.",
41 | reply_markup=InlineKeyboardMarkup(
42 | [[InlineKeyboardButton("Contact Support", url=BAN_SUPPORT)]]
43 | )
44 | )
45 | # ✅ Check Force Subscription
46 | if not await is_subscribed(client, user_id):
47 | #await temp.delete()
48 | return await not_joined(client, message)
49 |
50 | # File auto-delete time in seconds (Set your desired time in seconds here)
51 | FILE_AUTO_DELETE = await db.get_del_timer() # Example: 3600 seconds (1 hour)
52 |
53 | # Add user if not already present
54 | if not await db.present_user(user_id):
55 | try:
56 | await db.add_user(user_id)
57 | except:
58 | pass
59 |
60 | # Handle normal message flow
61 | text = message.text
62 | if len(text) > 7:
63 | try:
64 | base64_string = text.split(" ", 1)[1]
65 | except IndexError:
66 | return
67 |
68 | string = await decode(base64_string)
69 | argument = string.split("-")
70 |
71 | ids = []
72 | if len(argument) == 3:
73 | try:
74 | start = int(int(argument[1]) / abs(client.db_channel.id))
75 | end = int(int(argument[2]) / abs(client.db_channel.id))
76 | ids = range(start, end + 1) if start <= end else list(range(start, end - 1, -1))
77 | except Exception as e:
78 | print(f"Error decoding IDs: {e}")
79 | return
80 |
81 | elif len(argument) == 2:
82 | try:
83 | ids = [int(int(argument[1]) / abs(client.db_channel.id))]
84 | except Exception as e:
85 | print(f"Error decoding ID: {e}")
86 | return
87 |
88 | temp_msg = await message.reply("Please wait...")
89 | try:
90 | messages = await get_messages(client, ids)
91 | except Exception as e:
92 | await message.reply_text("Something went wrong!")
93 | print(f"Error getting messages: {e}")
94 | return
95 | finally:
96 | await temp_msg.delete()
97 |
98 | codeflix_msgs = []
99 |
100 | for msg in messages:
101 | original_caption = msg.caption.html if msg.caption else ""
102 | caption = f"{original_caption}\n\n{CUSTOM_CAPTION}" if CUSTOM_CAPTION else original_caption
103 | reply_markup = msg.reply_markup if DISABLE_CHANNEL_BUTTON else None
104 |
105 | try:
106 | snt_msg = await msg.copy(
107 | chat_id=message.from_user.id,
108 | caption=caption,
109 | parse_mode=ParseMode.HTML,
110 | reply_markup=reply_markup,
111 | protect_content=PROTECT_CONTENT
112 | )
113 | await asyncio.sleep(0.5)
114 | codeflix_msgs.append(snt_msg)
115 | except FloodWait as e:
116 | await asyncio.sleep(e.x)
117 | copied_msg = await msg.copy(
118 | chat_id=message.from_user.id,
119 | caption=caption,
120 | parse_mode=ParseMode.HTML,
121 | reply_markup=reply_markup,
122 | protect_content=PROTECT_CONTENT
123 | )
124 | codeflix_msgs.append(copied_msg)
125 | except:
126 | pass
127 |
128 | if FILE_AUTO_DELETE > 0:
129 | notification_msg = await message.reply(
130 | f"Tʜɪs Fɪʟᴇ ᴡɪʟʟ ʙᴇ Dᴇʟᴇᴛᴇᴅ ɪɴ {get_exp_time(FILE_AUTO_DELETE)}. Pʟᴇᴀsᴇ sᴀᴠᴇ ᴏʀ ғᴏʀᴡᴀʀᴅ ɪᴛ ᴛᴏ ʏᴏᴜʀ sᴀᴠᴇᴅ ᴍᴇssᴀɢᴇs ʙᴇғᴏʀᴇ ɪᴛ ɢᴇᴛs Dᴇʟᴇᴛᴇᴅ."
131 | )
132 |
133 | await asyncio.sleep(FILE_AUTO_DELETE)
134 |
135 | for snt_msg in codeflix_msgs:
136 | if snt_msg:
137 | try:
138 | await snt_msg.delete()
139 | except Exception as e:
140 | print(f"Error deleting message {snt_msg.id}: {e}")
141 |
142 | try:
143 | reload_url = (
144 | f"https://t.me/{client.username}?start={message.command[1]}"
145 | if message.command and len(message.command) > 1
146 | else None
147 | )
148 | keyboard = InlineKeyboardMarkup(
149 | [[InlineKeyboardButton("ɢᴇᴛ ғɪʟᴇ ᴀɢᴀɪɴ!", url=reload_url)]]
150 | ) if reload_url else None
151 |
152 | await notification_msg.edit(
153 | "ʏᴏᴜʀ ᴠɪᴅᴇᴏ / ꜰɪʟᴇ ɪꜱ ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ ᴅᴇʟᴇᴛᴇᴅ !!\n\nᴄʟɪᴄᴋ ʙᴇʟᴏᴡ ʙᴜᴛᴛᴏɴ ᴛᴏ ɢᴇᴛ ʏᴏᴜʀ ᴅᴇʟᴇᴛᴇᴅ ᴠɪᴅᴇᴏ / ꜰɪʟᴇ 👇",
154 | reply_markup=keyboard
155 | )
156 | except Exception as e:
157 | print(f"Error updating notification with 'Get File Again' button: {e}")
158 | else:
159 | reply_markup = InlineKeyboardMarkup(
160 | [
161 | [InlineKeyboardButton("• ᴍᴏʀᴇ ᴄʜᴀɴɴᴇʟs •", url="https://t.me/Nova_Flix/50")],
162 |
163 | [
164 | InlineKeyboardButton("• ᴀʙᴏᴜᴛ", callback_data = "about"),
165 | InlineKeyboardButton('ʜᴇʟᴘ •', callback_data = "help")
166 |
167 | ]
168 | ]
169 | )
170 | await message.reply_photo(
171 | photo=START_PIC,
172 | caption=START_MSG.format(
173 | first=message.from_user.first_name,
174 | last=message.from_user.last_name,
175 | username=None if not message.from_user.username else '@' + message.from_user.username,
176 | mention=message.from_user.mention,
177 | id=message.from_user.id
178 | ),
179 | reply_markup=reply_markup,
180 | message_effect_id=5104841245755180586) # 🔥
181 |
182 | return
183 |
184 |
185 |
186 | #=====================================================================================##
187 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888
188 | # Ask Doubt on telegram @CodeflixSupport
189 |
190 |
191 |
192 | # Create a global dictionary to store chat data
193 | chat_data_cache = {}
194 |
195 | async def not_joined(client: Client, message: Message):
196 | temp = await message.reply("ᴡᴀɪᴛ ᴀ sᴇᴄ..")
197 |
198 | user_id = message.from_user.id
199 | buttons = []
200 | count = 0
201 |
202 | try:
203 | all_channels = await db.show_channels() # Should return list of (chat_id, mode) tuples
204 | for total, chat_id in enumerate(all_channels, start=1):
205 | mode = await db.get_channel_mode(chat_id) # fetch mode
206 |
207 | await message.reply_chat_action(ChatAction.TYPING)
208 |
209 | if not await is_sub(client, user_id, chat_id):
210 | try:
211 | # Cache chat info
212 | if chat_id in chat_data_cache:
213 | data = chat_data_cache[chat_id]
214 | else:
215 | data = await client.get_chat(chat_id)
216 | chat_data_cache[chat_id] = data
217 |
218 | name = data.title
219 |
220 | # Generate proper invite link based on the mode
221 | if mode == "on" and not data.username:
222 | invite = await client.create_chat_invite_link(
223 | chat_id=chat_id,
224 | creates_join_request=True,
225 | expire_date=datetime.utcnow() + timedelta(seconds=FSUB_LINK_EXPIRY) if FSUB_LINK_EXPIRY else None
226 | )
227 | link = invite.invite_link
228 |
229 | else:
230 | if data.username:
231 | link = f"https://t.me/{data.username}"
232 | else:
233 | invite = await client.create_chat_invite_link(
234 | chat_id=chat_id,
235 | expire_date=datetime.utcnow() + timedelta(seconds=FSUB_LINK_EXPIRY) if FSUB_LINK_EXPIRY else None)
236 | link = invite.invite_link
237 |
238 | buttons.append([InlineKeyboardButton(text=name, url=link)])
239 | count += 1
240 | await temp.edit(f"{'! ' * count}")
241 |
242 | except Exception as e:
243 | print(f"Error with chat {chat_id}: {e}")
244 | return await temp.edit(
245 | f"! Eʀʀᴏʀ, Cᴏɴᴛᴀᴄᴛ ᴅᴇᴠᴇʟᴏᴘᴇʀ ᴛᴏ sᴏʟᴠᴇ ᴛʜᴇ ɪssᴜᴇs @rohit_1888\n"
246 | f"Rᴇᴀsᴏɴ: {e}" 247 | ) 248 | 249 | # Retry Button 250 | try: 251 | buttons.append([ 252 | InlineKeyboardButton( 253 | text='♻️ Tʀʏ Aɢᴀɪɴ', 254 | url=f"https://t.me/{client.username}?start={message.command[1]}" 255 | ) 256 | ]) 257 | except IndexError: 258 | pass 259 | 260 | await message.reply_photo( 261 | photo=FORCE_PIC, 262 | caption=FORCE_MSG.format( 263 | first=message.from_user.first_name, 264 | last=message.from_user.last_name, 265 | username=None if not message.from_user.username else '@' + message.from_user.username, 266 | mention=message.from_user.mention, 267 | id=message.from_user.id 268 | ), 269 | reply_markup=InlineKeyboardMarkup(buttons), 270 | ) 271 | 272 | except Exception as e: 273 | print(f"Final Error: {e}") 274 | await temp.edit( 275 | f"! Eʀʀᴏʀ, Cᴏɴᴛᴀᴄᴛ ᴅᴇᴠᴇʟᴏᴘᴇʀ ᴛᴏ sᴏʟᴠᴇ ᴛʜᴇ ɪssᴜᴇs @rohit_1888\n" 276 | f"
Rᴇᴀsᴏɴ: {e}" 277 | ) 278 | 279 | #=====================================================================================## 280 | 281 | @Bot.on_message(filters.command('commands') & filters.private & admin) 282 | async def bcmd(bot: Bot, message: Message): 283 | reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("• ᴄʟᴏsᴇ •", callback_data = "close")]]) 284 | await message.reply(text=CMD_TXT, reply_markup = reply_markup, quote= True) 285 | -------------------------------------------------------------------------------- /plugins/useless.py: -------------------------------------------------------------------------------- 1 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888 2 | # Ask Doubt on telegram @CodeflixSupport 3 | # 4 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >. 5 | # 6 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project, 7 | # and is released under the MIT License. 8 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE > 9 | # 10 | # All rights reserved. 11 | # 12 | 13 | import asyncio 14 | import os 15 | import random 16 | import sys 17 | import time 18 | from datetime import datetime, timedelta 19 | from pyrogram import Client, filters, __version__ 20 | from pyrogram.enums import ParseMode, ChatAction 21 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery, ReplyKeyboardMarkup, ChatInviteLink, ChatPrivileges 22 | from pyrogram.errors.exceptions.bad_request_400 import UserNotParticipant 23 | from pyrogram.errors import FloodWait, UserIsBlocked, InputUserDeactivated, UserNotParticipant 24 | from bot import Bot 25 | from config import * 26 | from helper_func import * 27 | from database.database import * 28 | 29 | #=====================================================================================## 30 | 31 | @Bot.on_message(filters.command('stats') & admin) 32 | async def stats(bot: Bot, message: Message): 33 | now = datetime.now() 34 | delta = now - bot.uptime 35 | time = get_readable_time(delta.seconds) 36 | await message.reply(BOT_STATS_TEXT.format(uptime=time)) 37 | 38 | 39 | #=====================================================================================## 40 | 41 | WAIT_MSG = "Working...." 42 | 43 | #=====================================================================================## 44 | 45 | 46 | @Bot.on_message(filters.command('users') & filters.private & admin) 47 | async def get_users(client: Bot, message: Message): 48 | msg = await client.send_message(chat_id=message.chat.id, text=WAIT_MSG) 49 | users = await db.full_userbase() 50 | await msg.edit(f"{len(users)} users are using this bot") 51 | 52 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888 53 | # Ask Doubt on telegram @CodeflixSupport 54 | # 55 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >. 56 | # 57 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project, 58 | # and is released under the MIT License. 59 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE > 60 | # 61 | # All rights reserved. 62 | # 63 | 64 | #=====================================================================================## 65 | 66 | #AUTO-DELETE 67 | 68 | @Bot.on_message(filters.private & filters.command('dlt_time') & admin) 69 | async def set_delete_time(client: Bot, message: Message): 70 | try: 71 | duration = int(message.command[1]) 72 | 73 | await db.set_del_timer(duration) 74 | 75 | await message.reply(f"Dᴇʟᴇᴛᴇ Tɪᴍᴇʀ ʜᴀs ʙᴇᴇɴ sᴇᴛ ᴛᴏ
{duration} sᴇᴄᴏɴᴅs.") 76 | 77 | except (IndexError, ValueError): 78 | await message.reply("Pʟᴇᴀsᴇ ᴘʀᴏᴠɪᴅᴇ ᴀ ᴠᴀʟɪᴅ ᴅᴜʀᴀᴛɪᴏɴ ɪɴ sᴇᴄᴏɴᴅs. Usage: /dlt_time {duration}") 79 | 80 | @Bot.on_message(filters.private & filters.command('check_dlt_time') & admin) 81 | async def check_delete_time(client: Bot, message: Message): 82 | duration = await db.get_del_timer() 83 | 84 | await message.reply(f"
Cᴜʀʀᴇɴᴛ ᴅᴇʟᴇᴛᴇ ᴛɪᴍᴇʀ ɪs sᴇᴛ ᴛᴏ {duration}sᴇᴄᴏɴᴅs.") 85 | 86 | #=====================================================================================## 87 | 88 | # Don't Remove Credit @CodeFlix_Bots, @rohit_1888 89 | # Ask Doubt on telegram @CodeflixSupport 90 | # 91 | # Copyright (C) 2025 by Codeflix-Bots@Github, < https://github.com/Codeflix-Bots >. 92 | # 93 | # This file is part of < https://github.com/Codeflix-Bots/FileStore > project, 94 | # and is released under the MIT License. 95 | # Please see < https://github.com/Codeflix-Bots/FileStore/blob/master/LICENSE > 96 | # 97 | # All rights reserved. 98 | # -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | #https://codeload.github.com/KurimuzonAkuma/pyrogram/zip/refs/heads/dev 2 | pyrofork==2.3.61 3 | TgCrypto 4 | pyromod==1.5 5 | schedule 6 | APscheduler 7 | # --- For-Database ------------ # 8 | pymongo 9 | motor 10 | dnspython 11 | # --- For-Web-Response ------- # 12 | aiohttp 13 | python-dotenv 14 | # --- For-Web-Response ------- # 15 | pytz 16 | requests 17 | bs4 18 | aiofiles 19 | asyncio 20 | --------------------------------------------------------------------------------