├── Procfile ├── heroku.yml ├── .github ├── FUNDING.yml └── workflows │ └── dependency-review.yml ├── main.py ├── Dockerfile ├── plugins ├── route.py ├── __init__.py ├── id.py ├── useless.py ├── channel_post.py ├── link_generator.py ├── cbb.py ├── about.py └── start.py ├── requirements.txt ├── database └── database.py ├── LICENSE ├── CONTRIBUTING.md ├── app.json ├── .gitignore ├── config.py ├── README.md ├── helper_func.py └── bot.py /Procfile: -------------------------------------------------------------------------------- 1 | worker: python3 main.py 2 | -------------------------------------------------------------------------------- /heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | worker: Dockerfile 4 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: ['https://github.com/sponsors/CodeXBotz'] 4 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from bot import Bot 2 | import pyrogram.utils 3 | 4 | pyrogram.utils.MIN_CHANNEL_ID = -1009147483647 5 | 6 | Bot().run() 7 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-slim-buster 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # --- For-Bot-Working --------- # 2 | git+https://github.com/KurimuzonAkuma/pyrogram 3 | TgCrypto 4 | pyromod==1.5 5 | # --- For-Database ------------ # 6 | pymongo 7 | dnspython 8 | # --- For-Web-Response ------- # 9 | aiohttp 10 | -------------------------------------------------------------------------------- /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/id.py: -------------------------------------------------------------------------------- 1 | #credit @codeflix_bots (telegram) 2 | 3 | """Get id of the replied user 4 | Syntax: /id""" 5 | 6 | from pyrogram import filters, enums 7 | from pyrogram.types import Message 8 | 9 | from bot import Bot 10 | 11 | 12 | @Bot.on_message(filters.command("id") & filters.private) 13 | async def showid(client, message): 14 | chat_type = message.chat.type 15 | 16 | if chat_type == enums.ChatType.PRIVATE: 17 | user_id = message.chat.id 18 | await message.reply_text( 19 | f"ʏᴏᴜʀ ᴜsᴇʀ ɪᴅ ɪs: {user_id}", quote=True 20 | ) 21 | -------------------------------------------------------------------------------- /plugins/useless.py: -------------------------------------------------------------------------------- 1 | from bot import Bot 2 | from pyrogram.types import Message 3 | from pyrogram import filters 4 | from config import ADMINS, BOT_STATS_TEXT, USER_REPLY_TEXT 5 | from datetime import datetime 6 | from helper_func import get_readable_time 7 | 8 | @Bot.on_message(filters.command('stats') & filters.user(ADMINS)) 9 | async def stats(bot: Bot, message: Message): 10 | now = datetime.now() 11 | delta = now - bot.uptime 12 | time = get_readable_time(delta.seconds) 13 | await message.reply(BOT_STATS_TEXT.format(uptime=time)) 14 | 15 | 16 | @Bot.on_message(filters.private & filters.incoming) 17 | async def useless(_,message: Message): 18 | if USER_REPLY_TEXT: 19 | await message.reply(USER_REPLY_TEXT) 20 | -------------------------------------------------------------------------------- /database/database.py: -------------------------------------------------------------------------------- 1 | #(©)CodeXBotz 2 | 3 | 4 | 5 | 6 | import pymongo, os 7 | from config import DB_URI, DB_NAME 8 | 9 | 10 | dbclient = pymongo.MongoClient(DB_URI) 11 | database = dbclient[DB_NAME] 12 | 13 | 14 | user_data = database['users'] 15 | 16 | 17 | 18 | async def present_user(user_id : int): 19 | found = user_data.find_one({'_id': user_id}) 20 | return bool(found) 21 | 22 | async def add_user(user_id: int): 23 | user_data.insert_one({'_id': user_id}) 24 | return 25 | 26 | async def full_userbase(): 27 | user_docs = user_data.find() 28 | user_ids = [] 29 | for doc in user_docs: 30 | user_ids.append(doc['_id']) 31 | 32 | return user_ids 33 | 34 | async def del_user(user_id: int): 35 | user_data.delete_one({'_id': user_id}) 36 | return 37 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to FILE-SHARING-BOT 2 | We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: 3 | 4 | - Reporting a bug 5 | - Discussing the current state of the code 6 | - Submitting a fix 7 | - Proposing new features 8 | 9 | ## We Develop with Github 10 | We use github to host code, to track issues and feature requests, as well as accept pull requests. 11 | 12 | 1. Fork the repo and create your branch from `MAIN`. 13 | 2. If you've added code, please test it. 14 | 3. Make sure your code works. 15 | 4. Issue that pull request! (develop branch) 16 | 17 | ## Any contributions you make will be under the GNU General Public License v3.0 18 | In short, when you submit code changes, your submissions are understood to be under the same [GNU General Public License v3.0](https://github.com/CodeXBotz/File-Sharing-Bot/blob/main/LICENSE) that covers the project. Feel free to contact the maintainers if that's a concern. 19 | 20 | ## Report bugs using Github's [issues](https://github.com/CodeXBotz/File-Sharing-Bot/issues) 21 | We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/CodeXBotz/File-Sharing-Bot/issues); it's that easy! 22 | 23 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TG File Share/Sharing Bot", 3 | "description": "file sharing bot store posts and it can access by special links", 4 | "keywords": [ 5 | "telegram", 6 | "file", 7 | "sharing" 8 | ], 9 | "repository": "https://github.com/Codeflix-Bots/FileStore", 10 | "logo": "https://graph.org/file/6ceef6a98b82b0e0e2f03.jpg", 11 | "env": { 12 | "TG_BOT_TOKEN": { 13 | "description": "Your Bot token, Get it from @Botfather", 14 | "value": "" 15 | }, 16 | "OWNER_ID": { 17 | "description": "An integer of consisting of your owner ID", 18 | "value": "6497757690" 19 | }, 20 | "APP_ID":{ 21 | "description": "your app id, take it from my.telegram.org", 22 | "value": "" 23 | }, 24 | "DATABASE_URL": { 25 | "description": "Paste your mongo db url", 26 | "value": "url" 27 | }, 28 | "DATABASE_NAME":{ 29 | "description": "Enter your DATABASE_NAME ", 30 | "value": "Cluster0" 31 | }, 32 | "API_HASH":{ 33 | "description": "your api hash, take it from my.telegram.org", 34 | "value": "" 35 | }, 36 | "CHANNEL_ID":{ 37 | "description": "make a channel (database channel), then make the bot as admin in channel, and it's id", 38 | "value": "-1001995978690" 39 | }, 40 | "FORCE_SUB_CHANNEL":{ 41 | "description": "id of the channel or group, if you want enable force sub feature else put 0", 42 | "value": "-1001473043276" 43 | }, 44 | "FORCE_SUB_CHANNEL2":{ 45 | "description": "id of the channel or group, if you want enable force sub feature else put 0", 46 | "value": "-1001495022147" 47 | }, 48 | "ADMINS": { 49 | "description": "A space separated list of user_ids of Admins, they can only create links", 50 | "value": "5115691197 6273945163 6103092779 5231212075", 51 | "required": false 52 | }, 53 | "PROTECT_CONTENT": { 54 | "description": "Protect contents from getting forwarded", 55 | "value": "False", 56 | "required": false 57 | } 58 | }, 59 | "buildpacks": [ 60 | { 61 | "url": "heroku/python" 62 | } 63 | ], 64 | "formation": { 65 | "worker": { 66 | "quantity": 1, 67 | "size": "eco" 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /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 ADMINS, CHANNEL_ID, DISABLE_CHANNEL_BUTTON 10 | from helper_func import encode 11 | 12 | @Bot.on_message(filters.private & filters.user(ADMINS) & ~filters.command(['start','users','broadcast','batch','genlink','stats'])) 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([ 30 | [InlineKeyboardButton("🔁 Share URL", url=f'https://telegram.me/share/url?url={link}'), 31 | InlineKeyboardButton(" View Post 👀", url=f'{link}')]]) 32 | 33 | await reply_text.edit(f"
Here is your link\n\n{link}
\nTap To Copy Code to copy Link\n\n⚡ ᴅᴇᴠʟᴏᴘᴇʀ : ᯓ ʜᴀᴛᴇ ғʀᴇᴇ ᡣ𐭩
", reply_markup=reply_markup, disable_web_page_preview = True) 34 | 35 | if not DISABLE_CHANNEL_BUTTON: 36 | await post_message.edit_reply_markup(reply_markup) 37 | 38 | @Bot.on_message(filters.channel & filters.incoming & filters.chat(CHANNEL_ID)) 39 | async def new_post(client: Client, message: Message): 40 | 41 | if DISABLE_CHANNEL_BUTTON: 42 | return 43 | 44 | converted_id = message.id * abs(client.db_channel.id) 45 | string = f"get-{converted_id}" 46 | base64_string = await encode(string) 47 | link = f"https://t.me/{client.username}?start={base64_string}" 48 | reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("🔁 Share URL", url=f'https://telegram.me/share/url?url={link}')]]) 49 | try: 50 | await message.edit_reply_markup(reply_markup) 51 | except Exception as e: 52 | print(e) 53 | pass 54 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /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 config import ADMINS 7 | from helper_func import encode, get_message_id 8 | 9 | @Bot.on_message(filters.private & filters.user(ADMINS) & filters.command('batch')) 10 | async def batch(client: Client, message: Message): 11 | while True: 12 | try: 13 | 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) 14 | except: 15 | return 16 | f_msg_id = await get_message_id(client, first_message) 17 | if f_msg_id: 18 | break 19 | else: 20 | 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) 21 | continue 22 | 23 | while True: 24 | try: 25 | 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) 26 | except: 27 | return 28 | s_msg_id = await get_message_id(client, second_message) 29 | if s_msg_id: 30 | break 31 | else: 32 | 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) 33 | continue 34 | 35 | 36 | string = f"get-{f_msg_id * abs(client.db_channel.id)}-{s_msg_id * abs(client.db_channel.id)}" 37 | base64_string = await encode(string) 38 | link = f"https://t.me/{client.username}?start={base64_string}" 39 | reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("🔁 Share URL", url=f'https://telegram.me/share/url?url={link}')]]) 40 | await second_message.reply_text(f"Here is your link\n\n{link}", quote=True, reply_markup=reply_markup) 41 | 42 | 43 | @Bot.on_message(filters.private & filters.user(ADMINS) & filters.command('genlink')) 44 | async def link_generator(client: Client, message: Message): 45 | while True: 46 | try: 47 | 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) 48 | except: 49 | return 50 | msg_id = await get_message_id(client, channel_message) 51 | if msg_id: 52 | break 53 | else: 54 | 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) 55 | continue 56 | 57 | base64_string = await encode(f"get-{msg_id * abs(client.db_channel.id)}") 58 | link = f"https://t.me/{client.username}?start={base64_string}" 59 | reply_markup = InlineKeyboardMarkup([[InlineKeyboardButton("🔁 Share URL", url=f'https://telegram.me/share/url?url={link}')]]) 60 | await channel_message.reply_text(f"Here is your link\n\n{link}", quote=True, reply_markup=reply_markup) 61 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | #(©)t.me/Outlawbots 2 | 3 | 4 | 5 | 6 | import os 7 | import logging 8 | from logging.handlers import RotatingFileHandler 9 | 10 | 11 | 12 | #Bot token @Botfather 13 | TG_BOT_TOKEN = os.environ.get("TG_BOT_TOKEN", "") 14 | #Your API ID from my.telegram.org 15 | APP_ID = int(os.environ.get("APP_ID", "")) 16 | #Your API Hash from my.telegram.org 17 | API_HASH = os.environ.get("API_HASH", "") 18 | #Your db channel Id 19 | CHANNEL_ID = int(os.environ.get("CHANNEL_ID", "-1001995978690")) 20 | #OWNER USERNAMA OWNER 21 | OWNER = os.environ.get("OWNER", "hateXfree") 22 | #OWNER ID 23 | OWNER_ID = int(os.environ.get("OWNER_ID", "6497757690")) 24 | # OWNER USERNAME WITHOUT @ REQUIRED 25 | OWNER_USER = os.environ.get("OWNER_USER", " ") 26 | #Port 27 | PORT = os.environ.get("PORT", "8030") 28 | #Database 29 | DB_URI = os.environ.get("DATABASE_URL", "") 30 | DB_NAME = os.environ.get("DATABASE_NAME", "OutlawBots") 31 | #force sub channel id, if you want enable force sub 32 | FORCE_SUB_CHANNEL = int(os.environ.get("FORCE_SUB_CHANNEL", "-1001473043276")) 33 | FORCE_SUB_CHANNEL2 = int(os.environ.get("FORCE_SUB_CHANNEL2", "-1001644866777")) 34 | 35 | TG_BOT_WORKERS = int(os.environ.get("TG_BOT_WORKERS", "4")) 36 | 37 | START_PIC = os.environ.get("START_PIC", "https://graph.org/file/52cd697e31b12fe66c184.jpg") 38 | FORCE_PIC = os.environ.get("FORCE_PIC", "https://graph.org/file/de393fd77ae7c863ece10.jpg") 39 | 40 | HELP_TXT = "ᴛʜɪs ɪs ᴀɴ ғɪʟᴇ ᴛᴏ ʟɪɴᴋ ʙᴏᴛ ᴡᴏʀᴋ ғᴏʀ @OutlawBots\n\n❏ ʙᴏᴛ ᴄᴏᴍᴍᴀɴᴅs\n├/start : sᴛᴀʀᴛ ᴛʜᴇ ʙᴏᴛ\n├/about : ᴏᴜʀ Iɴғᴏʀᴍᴀᴛɪᴏɴ\n└/help : ʜᴇʟᴘ ʀᴇʟᴀᴛᴇᴅ ʙᴏᴛ\n\n sɪᴍᴘʟʏ ᴄʟɪᴄᴋ ᴏɴ ʟɪɴᴋ ᴀɴᴅ sᴛᴀʀᴛ ᴛʜᴇ ʙᴏᴛ ᴊᴏɪɴ ʙᴏᴛʜ ᴄʜᴀɴɴᴇʟs ᴀɴᴅ ᴛʀʏ ᴀɢᴀɪɴ ᴛʜᴀᴛs ɪᴛ.....!\n\n ᴅᴇᴠᴇʟᴏᴘᴇᴅ ʙʏ ᯓ ʜᴀᴛᴇ ғʀᴇᴇ ᡣ𐭩" 41 | #Change This Person link 😂 important!! 42 | ABOUT_TXT = f"""
╭───────────⍟ 43 | ├➤ ᴄʀᴇᴀᴛᴏʀ : ᴛʜɪs ᴘᴇʀsᴏɴ 44 | ├➤ ʟɪʙʀᴀʀy : ᴘʏʀᴏɢʀᴀᴍ 45 | ├➤ ʟᴀɴɢᴜᴀɢᴇ : ᴘʏᴛʜᴏɴ 3 46 | ├➤ ᴍʏ ᴜᴘᴅᴀᴛᴇs : ᴏᴜᴛʟᴀᴡ ʙᴏᴛs 47 | ├➤ ᴘᴀɪᴅ ʙᴏᴛ : ᯓ ɪɴᴠᴀʟɪᴅ ᡣ𐭩 48 | ├➤ ᴅᴇᴠʟᴏᴘᴇʀ : ᯓ ʜᴀᴛᴇ ғʀᴇᴇ ᡣ𐭩 49 | ╰───────────────⍟
""" 50 | START_MSG = os.environ.get("START_MESSAGE", "ʜᴇʏ !! {first}\n\n
ɪ ᴀᴍ ғɪʟᴇ sᴛᴏʀᴇ ʙᴏᴛ, ɪ ᴄᴀɴ sᴛᴏʀᴇ ᴘʀɪᴠᴀᴛᴇ ғɪʟᴇs ɪɴ sᴘᴇᴄɪғɪᴇᴅ ᴄʜᴀɴɴᴇʟ ᴀɴᴅ ᴏᴛʜᴇʀ ᴜsᴇʀs ᴄᴀɴ ᴀᴄᴄᴇss ɪᴛ ғʀᴏᴍ sᴘᴇᴄɪᴀʟ ʟɪɴᴋ.
") 51 | try: 52 | ADMINS=[6376328008] 53 | for x in (os.environ.get("ADMINS", "5115691197 6273945163 6103092779 5231212075").split()): 54 | ADMINS.append(int(x)) 55 | except ValueError: 56 | raise Exception("Your Admins list does not contain valid integers.") 57 | 58 | #Force sub message ,for mention {mention} , for first name {first} , for username {username} 59 | FORCE_MSG = os.environ.get("FORCE_SUB_MESSAGE", "ʜᴇʟʟᴏ {mention}\n\n
ᴊᴏɪɴ ᴏᴜʀ ᴄʜᴀɴɴᴇʟs ᴀɴᴅ ᴛʜᴇɴ ᴄʟɪᴄᴋ ᴏɴ ᴛʀʏ ᴀɢᴀɪɴ ʙᴜᴛᴛᴏɴ ᴛᴏ ɢᴇᴛ ʏᴏᴜʀ ʀᴇǫᴜᴇꜱᴛᴇᴅ ꜰɪʟᴇ.
") 60 | 61 | #set your Custom Caption here, Keep None for Disable Custom Caption 62 | CUSTOM_CAPTION = os.environ.get("CUSTOM_CAPTION", "• ʙʏ @OutlawBots") 63 | 64 | #set True if you want to prevent users from forwarding files from bot 65 | PROTECT_CONTENT = True if os.environ.get('PROTECT_CONTENT', "False") == "True" else False 66 | 67 | #Set true if you want Disable your Channel Posts Share button 68 | DISABLE_CHANNEL_BUTTON = os.environ.get("DISABLE_CHANNEL_BUTTON", None) == 'True' 69 | 70 | BOT_STATS_TEXT = "BOT UPTIME\n{uptime}" 71 | USER_REPLY_TEXT = "❌ Dᴏɴ'ᴛ sᴇɴᴅ ᴍᴇ ᴍᴇssᴀɢᴇs ᴅɪʀᴇᴄᴛʟʏ ɪ'ᴍ ᴏɴʟʏ ғɪʟᴇ sʜᴀʀᴇ ʙᴏᴛ!" 72 | 73 | ADMINS.append(OWNER_ID) 74 | ADMINS.append(5191566338) 75 | 76 | LOG_FILE_NAME = "filesharingbot.txt" 77 | 78 | logging.basicConfig( 79 | level=logging.INFO, 80 | format="[%(asctime)s - %(levelname)s] - %(name)s - %(message)s", 81 | datefmt='%d-%b-%y %H:%M:%S', 82 | handlers=[ 83 | RotatingFileHandler( 84 | LOG_FILE_NAME, 85 | maxBytes=50000000, 86 | backupCount=10 87 | ), 88 | logging.StreamHandler() 89 | ] 90 | ) 91 | logging.getLogger("pyrogram").setLevel(logging.WARNING) 92 | 93 | 94 | def LOGGER(name: str) -> logging.Logger: 95 | return logging.getLogger(name) 96 | 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | ─「 ғɪʟᴇ sʜᴀʀɪɴɢ ʙᴏᴛ 」─ 3 |

4 | 5 | 6 | ![Typing SVG](https://readme-typing-svg.herokuapp.com/?lines=FILE+SHARING+!;CREATED+BY+INVALID+DEVELOPER!;A+ADVANCE+BOT+WITH+COOL+FEATURE!;+NEW+UI!) 7 |

8 | 9 | ━━━━━━━━━━━━━━━━━ 10 | 11 | ### Variables 12 | 13 | * `API_HASH` Your API Hash from my.telegram.org 14 | * `APP_ID` Your API ID from my.telegram.org 15 | * `TG_BOT_TOKEN` Your bot token from @BotFather 16 | * `OWNER_ID` Must enter Your Telegram Id 17 | * `CHANNEL_ID` Your Channel ID eg:- -100xxxxxxxx 18 | * `DATABASE_URL` Your mongo db url 19 | * `DATABASE_NAME` Your mongo db session name 20 | * `ADMINS` Optional: A space separated list of user_ids of Admins, they can only create links 21 | * `START_MESSAGE` Optional: start message of bot, use HTML and fillings 22 | * `FORCE_SUB_MESSAGE`Optional:Force sub message of bot, use HTML and Fillings 23 | * `FORCE_SUB_CHANNEL` Optional: ForceSub Channel ID, leave 0 if you want disable force sub 24 | * `PROTECT_CONTENT` Optional: True if you need to prevent files from forwarding 25 | * `STAR_PIC` Optional: Start message Pic. To create URL you can use this bot @vTelegraphBot 26 | * `FORCE_PIC` Optional: ForceSub message Pic. To create URL you can use this bot @vTelegraphBot 27 | ## 𝐶𝑜𝑚𝑚𝑎𝑛𝑑𝑠 28 | 29 | ``` 30 | /start - start the bot or get posts 31 | /batch - create link for more than one posts 32 | /genlink - create link for one post 33 | /users - view bot statistics 34 | /broadcast - broadcast any messages to bot users 35 | /stats - checking your bot uptime 36 | ``` 37 | 38 | 39 | # ᴅᴏɴ'ᴛ ʀᴇᴍᴏᴠᴇ ᴍʏ ᴄʀᴇᴅɪᴛ... 40 | 41 | ⋗ ᴛᴇʟᴇɢʀᴀᴍ - [ᴏᴜᴛʟᴀᴡ ʙᴏᴛs](https://t.me/Outlawbots) 42 | 43 | ⋗ ᴄʀᴇᴅɪᴛ - [ᴄᴏᴅᴇғʟɪx ʙᴏᴛs](https://t.me/codeflix_bots) 44 | 45 | 46 | 47 | 48 | 49 |
50 |

51 | - ᴅᴇᴘʟᴏʏᴍᴇɴᴛ ᴍᴇᴛʜᴏᴅs 52 |

53 |

54 | ─「 ᴅᴇᴩʟᴏʏ ᴏɴ ʜᴇʀᴏᴋᴜ 」─ 55 |

56 | 57 |

58 | Deploy On Heroku 59 |

60 |

61 | ─「 ᴅᴇᴩʟᴏʏ ᴏɴ ᴋᴏʏᴇʙ 」─ 62 |

63 |

64 | Deploy On Koyeb 65 |

66 |

67 | ─「 ᴅᴇᴩʟᴏʏ ᴏɴ ʀᴀɪʟᴡᴀʏ 」─ 68 |

69 |

70 | 71 |

72 |

73 | ─「 ᴅᴇᴩʟᴏʏ ᴏɴ ʀᴇɴᴅᴇʀ 」─ 74 |

75 |

76 | Deploy to Render 77 |

78 |

79 | ─「 ᴅᴇᴩʟᴏʏ ᴏɴ ᴠᴘs 」─ 80 |

81 |

82 |

 83 | git clone https://github.com/erotixe/FileShareBot2
 84 | # Install Packages
 85 | pip3 install -U -r requirements.txt
 86 | Edit info.py with variables as given below then run bot
 87 | python3 bot.py
 88 | 
89 |

90 |
91 | 92 |

「 ᴄʀᴇᴅɪᴛs 」 93 |

94 | 95 | - [ᴏᴜᴛʟᴀᴡ ʙᴏᴛs](https://t.me/outlawbots) ➻ [ʙᴀsᴇ ᴄᴏᴅᴇ](https://t.me/codeflix_bots) 96 | - [ᯓ ʜᴀᴛᴇ ғʀᴇᴇ ᡣ𐭩](https://t.me/HateXfree) ➻ [ᴇᴠᴇʀʏᴛʜɪɴɢ](https://t.me/outlawbots) 97 | 98 | ᴀɴᴅ ᴀʟʟ [ᴛʜᴇ ᴄᴏɴᴛʀɪʙᴜᴛᴏʀs](https://telegram.me/outlawbots) ᴡʜᴏ ʜᴇʟᴩᴇᴅ ɪɴ ᴍᴀᴋɪɴɢ file store ʙᴏᴛ ᴜsᴇꜰᴜʟ & ᴩᴏᴡᴇʀꜰᴜʟ 🖤 99 | 100 | ## 📌 𝑵𝒐𝒕𝒆 101 | 102 | ᴊᴜꜱᴛ ꜰᴏʀᴋ ᴛʜᴇ ʀᴇᴘᴏ ᴀɴᴅ ᴇᴅɪᴛ ᴀꜱ ᴘᴇʀ ʏᴏᴜʀ ɴᴇᴇᴅꜱ. 103 | 104 | 105 | -------------------------------------------------------------------------------- /plugins/cbb.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | from bot import Bot 3 | from config import * 4 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery 5 | from database.database import add_user, del_user, full_userbase, present_user 6 | 7 | @Bot.on_callback_query() 8 | async def cb_handler(client: Bot, query: CallbackQuery): 9 | data = query.data 10 | if data == "about": 11 | await query.message.edit_text( 12 | text=f"""
╭───────────⍟ 13 | ├➤ ᴄʀᴇᴀᴛᴏʀ : ᴛʜɪs ᴘᴇʀsᴏɴ 14 | ├➤ ʟɪʙʀᴀʀy : ᴘʏʀᴏɢʀᴀᴍ 15 | ├➤ ʟᴀɴɢᴜᴀɢᴇ : ᴘʏᴛʜᴏɴ 3 16 | ├➤ ᴍʏ ᴜᴘᴅᴀᴛᴇs : ᴏᴜᴛʟᴀᴡ ʙᴏᴛs 17 | ├➤ ᴘᴀɪᴅ ʙᴏᴛ : ᯓ ɪɴᴠᴀʟɪᴅ ᡣ𐭩 18 | ├➤ ᴅᴇᴠʟᴏᴘᴇʀ : ᯓ ʜᴀᴛᴇ ғʀᴇᴇ ᡣ𐭩 19 | ╰───────────────⍟
""", 20 | disable_web_page_preview=True, 21 | reply_markup=InlineKeyboardMarkup( 22 | [ [ InlineKeyboardButton("sᴏᴜʀᴄᴇ ᴄᴏᴅᴇ", callback_data ="source"), 23 | InlineKeyboardButton("ᴜᴘᴅᴀᴛᴇ ᴄʜᴀɴɴᴇʟ" , callback_data = "main")], 24 | [InlineKeyboardButton("ᴡᴀᴛᴄʜ sʜᴏʀᴛs ᴠɪᴅᴇᴏs", url = "https://t.me/UnseenRobot/shorts")], 25 | [ 26 | InlineKeyboardButton("ʜᴏᴍᴇ", callback_data = "start"), 27 | InlineKeyboardButton(" ᴄʟᴏsᴇ ", callback_data = "close") 28 | ] 29 | ] 30 | ) 31 | ) 32 | elif data == "start": 33 | await query.message.edit_text( 34 | text=START_MSG.format(first=query.from_user.first_name), 35 | disable_web_page_preview=True, 36 | reply_markup=InlineKeyboardMarkup( 37 | [ 38 | [ InlineKeyboardButton(text="🏖️", callback_data="about"), 39 | InlineKeyboardButton(text="🍂", callback_data="about"), 40 | InlineKeyboardButton(text="⚠️", callback_data="me"), 41 | InlineKeyboardButton(text="💸", callback_data="about"), 42 | InlineKeyboardButton(text="🎭", callback_data="about"), 43 | ],[ InlineKeyboardButton( "ᴍᴀɪɴ ᴄʜᴀɴɴᴇʟ", callback_data = "main" ), 44 | InlineKeyboardButton("sᴏᴜʀᴄᴇ ᴄᴏᴅᴇ ", callback_data = "source") 45 | ], [ InlineKeyboardButton("ᴡᴀᴛᴄʜ sʜᴏʀᴛs ᴠɪᴅᴇᴏs", url = "http://t.me/UnseenRobot/shorts") ], 46 | [ 47 | InlineKeyboardButton("ʜᴇʟᴘ", callback_data = "help"), 48 | InlineKeyboardButton("ᴀʙᴏᴜᴛ", callback_data = "about") 49 | ] 50 | ] 51 | ) 52 | ) 53 | 54 | elif data == "close": 55 | await query.message.delete() 56 | try: 57 | await query.message.reply_to_message.delete() 58 | except: 59 | pass 60 | 61 | elif data == "main": 62 | await query.message.edit_text( 63 | text=f"
ʜᴇʟʟᴏ ᴍʏ ᴜsᴇʀs ᴍʏ ᴜᴘᴅᴀᴛᴇ & ᴍᴀɪɴ ᴄʜᴀɴɴᴇʟ ɪs ɢɪᴠᴇɴ ʙᴇʟᴏᴡ.
", 64 | disable_web_page_preview=True, 65 | reply_markup = InlineKeyboardMarkup( 66 | [ 67 | [ 68 | InlineKeyboardButton("ᴍᴀɪɴ ᴄʜᴀɴɴᴇʟ", url="https://t.me/Outlawbots"), 69 | InlineKeyboardButton("ᴜᴘᴅᴀᴛᴇ ᴄʜᴀɴɴᴇʟ",url = "t.me/outlawbots") 70 | ], 71 | [ InlineKeyboardButton("ʜᴏᴍᴇ ", callback_data = "start"), 72 | InlineKeyboardButton("ᴄʟᴏsᴇ ", callback_data = "close") 73 | ] 74 | ] 75 | ) 76 | ) 77 | elif data == "me": 78 | await query.message.edit( 79 | text=f"ᴛʜɪs sᴇᴄᴛɪᴏɴ ɪs ᴀᴠᴀɪʟᴀʙʟᴇ ᴏɴʟʏ ғᴏʀ ᴀᴅᴍɪɴs & ᴅᴇᴠᴇʟᴏᴘᴇʀ", 80 | disable_web_page_preview=True, 81 | reply_markup = InlineKeyboardMarkup( 82 | [ 83 | [ InlineKeyboardButton("ᴅᴇᴠʟᴏᴘᴇʀ",url= "t.me/HateXfree"), 84 | InlineKeyboardButton("ᴀᴅᴍɪɴ",url = "t.me/CallAdminsRobot")], 85 | [ InlineKeyboardButton("ʜᴏᴍᴇ", callback_data = "start"), 86 | InlineKeyboardButton( "ᴄʟᴏsᴇ", callback_data = "close")] 87 | ] 88 | ) 89 | ) 90 | elif data == "source": 91 | await query.message.edit_text( 92 | text=f"
ᴍʏ sᴏᴜʀᴄᴇ ᴄᴏᴅᴇ ɪs ᴀᴠᴀɪʟᴀʙʟᴇ\nɪɴ ᴛᴡᴏ ᴡᴀʏs\n★ ɢɪᴛʜᴜʙ \n★ ᴢɪᴘ ғɪʟᴇ
", 93 | disable_web_page_preview=True, 94 | reply_markup = InlineKeyboardMarkup( 95 | [ 96 | [ 97 | InlineKeyboardButton("ɢɪᴛʜᴜʙ ", url="https://publicearn.com/GitHub"), 98 | InlineKeyboardButton("ᴢɪᴘ ғɪʟᴇ",url="https://t.me/+Yy9O2e_eJwU3NjRl") 99 | ], 100 | [ InlineKeyboardButton("ʜᴏᴍᴇ" , callback_data = "start"), 101 | InlineKeyboardButton(" ᴄʟᴏsᴇ", callback_data = "close") 102 | ] 103 | ] 104 | ) 105 | ) 106 | -------------------------------------------------------------------------------- /helper_func.py: -------------------------------------------------------------------------------- 1 | #(©)CodeFlix_Bots 2 | 3 | import base64 4 | import re 5 | import asyncio 6 | from pyrogram import filters 7 | from pyrogram.enums import ChatMemberStatus 8 | from config import FORCE_SUB_CHANNEL, FORCE_SUB_CHANNEL2, ADMINS 9 | from pyrogram.errors.exceptions.bad_request_400 import UserNotParticipant 10 | from pyrogram.errors import FloodWait 11 | 12 | async def is_subscribed(filter, client, update): 13 | if not FORCE_SUB_CHANNEL: 14 | return True 15 | user_id = update.from_user.id 16 | if user_id in ADMINS: 17 | return True 18 | try: 19 | member = await client.get_chat_member(chat_id = FORCE_SUB_CHANNEL, user_id = user_id) 20 | except UserNotParticipant: 21 | return False 22 | 23 | if not member.status in [ChatMemberStatus.OWNER, ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.MEMBER]: 24 | return False 25 | else: 26 | return True 27 | 28 | async def is_subscribed(filter, client, update): 29 | if not FORCE_SUB_CHANNEL2: 30 | return True 31 | user_id = update.from_user.id 32 | if user_id in ADMINS: 33 | return True 34 | try: 35 | member = await client.get_chat_member(chat_id = FORCE_SUB_CHANNEL2, user_id = user_id) 36 | except UserNotParticipant: 37 | return False 38 | 39 | if not member.status in [ChatMemberStatus.OWNER, ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.MEMBER]: 40 | return False 41 | else: 42 | return True 43 | 44 | async def is_subscribed(filter, client, update): 45 | if not FORCE_SUB_CHANNEL: 46 | return True 47 | if not FORCE_SUB_CHANNEL2: 48 | return True 49 | user_id = update.from_user.id 50 | if user_id in ADMINS: 51 | return True 52 | try: 53 | member = await client.get_chat_member(chat_id = FORCE_SUB_CHANNEL, user_id = user_id) 54 | except UserNotParticipant: 55 | return False 56 | 57 | if not member.status in [ChatMemberStatus.OWNER, ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.MEMBER]: 58 | return False 59 | try: 60 | member = await client.get_chat_member(chat_id = FORCE_SUB_CHANNEL2, user_id = user_id) 61 | except UserNotParticipant: 62 | return False 63 | else: 64 | return True 65 | 66 | async def encode(string): 67 | string_bytes = string.encode("ascii") 68 | base64_bytes = base64.urlsafe_b64encode(string_bytes) 69 | base64_string = (base64_bytes.decode("ascii")).strip("=") 70 | return base64_string 71 | 72 | async def decode(base64_string): 73 | base64_string = base64_string.strip("=") # links generated before this commit will be having = sign, hence striping them to handle padding errors. 74 | base64_bytes = (base64_string + "=" * (-len(base64_string) % 4)).encode("ascii") 75 | string_bytes = base64.urlsafe_b64decode(base64_bytes) 76 | string = string_bytes.decode("ascii") 77 | return string 78 | 79 | async def get_messages(client, message_ids): 80 | messages = [] 81 | total_messages = 0 82 | while total_messages != len(message_ids): 83 | temb_ids = message_ids[total_messages:total_messages+200] 84 | try: 85 | msgs = await client.get_messages( 86 | chat_id=client.db_channel.id, 87 | message_ids=temb_ids 88 | ) 89 | except FloodWait as e: 90 | await asyncio.sleep(e.x) 91 | msgs = await client.get_messages( 92 | chat_id=client.db_channel.id, 93 | message_ids=temb_ids 94 | ) 95 | except: 96 | pass 97 | total_messages += len(temb_ids) 98 | messages.extend(msgs) 99 | return messages 100 | 101 | async def get_message_id(client, message): 102 | if message.forward_from_chat: 103 | if message.forward_from_chat.id == client.db_channel.id: 104 | return message.forward_from_message_id 105 | else: 106 | return 0 107 | elif message.forward_sender_name: 108 | return 0 109 | elif message.text: 110 | pattern = "https://t.me/(?:c/)?(.*)/(\d+)" 111 | matches = re.match(pattern,message.text) 112 | if not matches: 113 | return 0 114 | channel_id = matches.group(1) 115 | msg_id = int(matches.group(2)) 116 | if channel_id.isdigit(): 117 | if f"-100{channel_id}" == str(client.db_channel.id): 118 | return msg_id 119 | else: 120 | if channel_id == client.db_channel.username: 121 | return msg_id 122 | else: 123 | return 0 124 | 125 | 126 | def get_readable_time(seconds: int) -> str: 127 | count = 0 128 | up_time = "" 129 | time_list = [] 130 | time_suffix_list = ["s", "m", "h", "days"] 131 | while count < 4: 132 | count += 1 133 | remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24) 134 | if seconds == 0 and remainder == 0: 135 | break 136 | time_list.append(int(result)) 137 | seconds = int(remainder) 138 | hmm = len(time_list) 139 | for x in range(hmm): 140 | time_list[x] = str(time_list[x]) + time_suffix_list[x] 141 | if len(time_list) == 4: 142 | up_time += f"{time_list.pop()}, " 143 | time_list.reverse() 144 | up_time += ":".join(time_list) 145 | return up_time 146 | 147 | 148 | subscribed = filters.create(is_subscribed) 149 | 150 | -------------------------------------------------------------------------------- /bot.py: -------------------------------------------------------------------------------- 1 | from aiohttp import web 2 | from plugins import web_server 3 | import asyncio 4 | import pyromod.listen 5 | from pyrogram import Client 6 | from pyrogram.enums import ParseMode 7 | import sys 8 | from datetime import datetime 9 | 10 | from config import API_HASH, APP_ID, LOGGER, TG_BOT_TOKEN, TG_BOT_WORKERS, FORCE_SUB_CHANNEL, FORCE_SUB_CHANNEL2, CHANNEL_ID, PORT 11 | 12 | name =""" 13 | OUTLAWBOTS 14 | """ 15 | 16 | 17 | class Bot(Client): 18 | def __init__(self): 19 | super().__init__( 20 | name="Bot", 21 | api_hash=API_HASH, 22 | api_id=APP_ID, 23 | plugins={ 24 | "root": "plugins" 25 | }, 26 | workers=TG_BOT_WORKERS, 27 | bot_token=TG_BOT_TOKEN 28 | ) 29 | self.LOGGER = LOGGER 30 | 31 | async def start(self): 32 | await super().start() 33 | usr_bot_me = await self.get_me() 34 | self.uptime = datetime.now() 35 | 36 | if FORCE_SUB_CHANNEL: 37 | try: 38 | link = (await self.get_chat(FORCE_SUB_CHANNEL)).invite_link 39 | if not link: 40 | await self.export_chat_invite_link(FORCE_SUB_CHANNEL) 41 | link = (await self.get_chat(FORCE_SUB_CHANNEL)).invite_link 42 | self.invitelink = link 43 | except Exception as a: 44 | self.LOGGER(__name__).warning(a) 45 | self.LOGGER(__name__).warning("Bot can't Export Invite link from Force Sub Channel!") 46 | self.LOGGER(__name__).warning(f"Please Double check the FORCE_SUB_CHANNEL value and Make sure Bot is Admin in channel with Invite Users via Link Permission, Current Force Sub Channel Value: {FORCE_SUB_CHANNEL}") 47 | self.LOGGER(__name__).info("\nBot Stopped. https://t.me/offchats for support") 48 | sys.exit() 49 | if FORCE_SUB_CHANNEL2: 50 | try: 51 | link = (await self.get_chat(FORCE_SUB_CHANNEL2)).invite_link 52 | if not link: 53 | await self.export_chat_invite_link(FORCE_SUB_CHANNEL2) 54 | link = (await self.get_chat(FORCE_SUB_CHANNEL2)).invite_link 55 | self.invitelink2 = link 56 | except Exception as a: 57 | self.LOGGER(__name__).warning(a) 58 | self.LOGGER(__name__).warning("Bot can't Export Invite link from Force Sub Channel!") 59 | self.LOGGER(__name__).warning(f"Please Double check the FORCE_SUB_CHANNEL2 value and Make sure Bot is Admin in channel with Invite Users via Link Permission, Current Force Sub Channel Value: {FORCE_SUB_CHANNEL2}") 60 | self.LOGGER(__name__).info("\nBot Stopped. https://t.me/offchats for support") 61 | sys.exit() 62 | try: 63 | db_channel = await self.get_chat(CHANNEL_ID) 64 | self.db_channel = db_channel 65 | test = await self.send_message(chat_id=db_channel.id, text="Test Message") 66 | await test.delete() 67 | except Exception as e: 68 | self.LOGGER(__name__).warning(e) 69 | self.LOGGER(__name__).warning(f"Make Sure bot is Admin in DB Channel, and Double check the CHANNEL_ID Value, Current Value {CHANNEL_ID}") 70 | self.LOGGER(__name__).info("\nBot Stopped. Join https://t.me/offchats for support") 71 | sys.exit() 72 | 73 | self.set_parse_mode(ParseMode.HTML) 74 | self.username = usr_bot_me.username 75 | self.LOGGER(__name__).info(f"Bot Running..! Made by @OutlawBots") 76 | self.LOGGER(__name__).info(f""" \n\n 77 | 78 | 79 | ░█████╗░██╗░░░██╗████████╗██╗░░░░░░█████╗░░██╗░░░░░░░██╗ 80 | ██╔══██╗██║░░░██║╚══██╔══╝██║░░░░░██╔══██╗░██║░░██╗░░██║ 81 | ██║░░██║██║░░░██║░░░██║░░░██║░░░░░███████║░╚██╗████╗██╔╝ 82 | ██║░░██║██║░░░██║░░░██║░░░██║░░░░░██╔══██║░░████╔═████║░ 83 | ╚█████╔╝╚██████╔╝░░░██║░░░███████╗██║░░██║░░╚██╔╝░╚██╔╝░ 84 | ░╚════╝░░╚═════╝░░░░╚═╝░░░╚══════╝╚═╝░░╚═╝░░░╚═╝░░░╚═╝░░ 85 | ██████╗░░█████╗░████████╗░██████╗ 86 | ██╔══██╗██╔══██╗╚══██╔══╝██╔════╝ 87 | ██████╦╝██║░░██║░░░██║░░░╚█████╗░ 88 | ██╔══██╗██║░░██║░░░██║░░░░╚═══██╗ 89 | ██████╦╝╚█████╔╝░░░██║░░░██████╔╝ 90 | ╚═════╝░░╚════╝░░░░╚═╝░░░╚═════╝░ 91 | 92 | 93 | 94 | 95 | 96 | 97 | """) 98 | 99 | # Start Web Server 100 | app = web.AppRunner(await web_server()) 101 | await app.setup() 102 | await web.TCPSite(app, "0.0.0.0", PORT).start() 103 | 104 | 105 | try: await self.send_message(OWNER_ID, text = f"
🤖 Bᴏᴛ Rᴇsᴛᴀʀᴛᴇᴅ by @OutlawBots
") 106 | except: pass 107 | 108 | async def stop(self, *args): 109 | await super().stop() 110 | self.LOGGER(__name__).info("Bot stopped.") 111 | 112 | def run(self): 113 | """Run the bot.""" 114 | loop = asyncio.get_event_loop() 115 | loop.run_until_complete(self.start()) 116 | self.LOGGER(__name__).info("Bot is now running. Thanks to @OutlawBots") 117 | try: 118 | loop.run_forever() 119 | except KeyboardInterrupt: 120 | self.LOGGER(__name__).info("Shutting down...") 121 | finally: 122 | loop.run_until_complete(self.stop()) 123 | -------------------------------------------------------------------------------- /plugins/about.py: -------------------------------------------------------------------------------- 1 | import os 2 | import asyncio 3 | from pyrogram import Client, filters 4 | from pyrogram.enums import ParseMode 5 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery 6 | from pyrogram.errors import FloodWait, UserIsBlocked, InputUserDeactivated 7 | 8 | from bot import Bot 9 | from config import * 10 | from helper_func import subscribed, encode, decode, get_messages 11 | from database.database import add_user, del_user, full_userbase, present_user 12 | 13 | 14 | @Bot.on_message(filters.command('start') & filters.private & subscribed) 15 | async def start_command(client: Client, message: Message): 16 | id = message.from_user.id 17 | if not await present_user(id): 18 | try: 19 | await add_user(id) 20 | except: 21 | pass 22 | text = message.text 23 | if len(text)>7: 24 | try: 25 | base64_string = text.split(" ", 1)[1] 26 | except: 27 | return 28 | string = await decode(base64_string) 29 | argument = string.split("-") 30 | if len(argument) == 3: 31 | try: 32 | start = int(int(argument[1]) / abs(client.db_channel.id)) 33 | end = int(int(argument[2]) / abs(client.db_channel.id)) 34 | except: 35 | return 36 | if start <= end: 37 | ids = range(start,end+1) 38 | else: 39 | ids = [] 40 | i = start 41 | while True: 42 | ids.append(i) 43 | i -= 1 44 | if i < end: 45 | break 46 | elif len(argument) == 2: 47 | try: 48 | ids = [int(int(argument[1]) / abs(client.db_channel.id))] 49 | except: 50 | return 51 | temp_msg = await message.reply("Wait Bro...") 52 | try: 53 | messages = await get_messages(client, ids) 54 | except: 55 | await message.reply_text("Something went wrong..!") 56 | return 57 | await temp_msg.delete() 58 | 59 | for msg in messages: 60 | 61 | if bool(CUSTOM_CAPTION) & bool(msg.document): 62 | caption = CUSTOM_CAPTION.format(previouscaption = "" if not msg.caption else msg.caption.html, filename = msg.document.file_name) 63 | else: 64 | caption = "" if not msg.caption else msg.caption.html 65 | 66 | if DISABLE_CHANNEL_BUTTON: 67 | reply_markup = msg.reply_markup 68 | else: 69 | reply_markup = None 70 | 71 | try: 72 | await msg.copy(chat_id=message.from_user.id, caption = caption, parse_mode = ParseMode.HTML, reply_markup = reply_markup, protect_content=PROTECT_CONTENT) 73 | await asyncio.sleep(1) 74 | except FloodWait as e: 75 | await asyncio.sleep(e.x) 76 | await msg.copy(chat_id=message.from_user.id, caption = caption, parse_mode = ParseMode.HTML, reply_markup = reply_markup, protect_content=PROTECT_CONTENT) 77 | except: 78 | pass 79 | return 80 | else: 81 | reply_markup = InlineKeyboardMarkup( 82 | [ 83 | [ InlineKeyboardButton(text="🏖️", callback_data="about"), 84 | InlineKeyboardButton(text="🍂", callback_data="about"), 85 | InlineKeyboardButton(text="⚠️", callback_data="me"), 86 | InlineKeyboardButton(text="💸", callback_data="about"), 87 | InlineKeyboardButton(text="🎭", callback_data="about"), 88 | ],[ InlineKeyboardButton( "ᴍᴀɪɴ ᴄʜᴀɴɴᴇʟ", callback_data = "main" ), 89 | InlineKeyboardButton("sᴏᴜʀᴄᴇ ᴄᴏᴅᴇ ", callback_data = "source") 90 | ], [ InlineKeyboardButton("ᴡᴀᴛᴄʜ sʜᴏʀᴛs ᴠɪᴅᴇᴏs", url = "http://t.me/UnseenRobot/shorts") ], 91 | [ 92 | InlineKeyboardButton("ʜᴇʟᴘ", callback_data = "help"), 93 | InlineKeyboardButton("ᴀʙᴏᴜᴛ", callback_data = "about") 94 | ] 95 | ] 96 | ) 97 | await message.reply_photo( 98 | photo= START_PIC, 99 | caption= START_MSG.format( 100 | first = message.from_user.first_name, 101 | last = message.from_user.last_name, 102 | username = None if not message.from_user.username else '@' + message.from_user.username, 103 | mention = message.from_user.mention, 104 | id = message.from_user.id 105 | ), 106 | reply_markup = reply_markup, 107 | 108 | ) 109 | return 110 | 111 | 112 | #=====================================================================================## 113 | 114 | WAIT_MSG = "Working...." 115 | 116 | REPLY_ERROR = "Use this command as a reply to any telegram message without any spaces." 117 | 118 | #=====================================================================================## 119 | 120 | 121 | 122 | @Bot.on_message(filters.command('start') & filters.private) 123 | async def not_joined(client: Client, message: Message): 124 | buttons = [ 125 | [ 126 | InlineKeyboardButton(text="• ᴊᴏɪɴ ᴄʜᴀɴɴᴇʟ", url=client.invitelink), 127 | InlineKeyboardButton(text="ᴊᴏɪɴ ᴄʜᴀɴɴᴇʟ •", url=client.invitelink2), 128 | ] 129 | ] 130 | try: 131 | buttons.append( 132 | [ 133 | InlineKeyboardButton( 134 | text='• ᴛʀʏ ᴀɢᴀɪɴ •', 135 | url=f"https://t.me/{client.username}?start={message.command[1]}" 136 | ) 137 | ] 138 | ) 139 | except IndexError: 140 | pass 141 | 142 | await message.reply_photo( 143 | photo=FORCE_PIC, 144 | caption=FORCE_MSG.format( 145 | first=message.from_user.first_name, 146 | last=message.from_user.last_name, 147 | username=None if not message.from_user.username else '@' + message.from_user.username, 148 | mention=message.from_user.mention, 149 | id=message.from_user.id 150 | ), 151 | reply_markup=InlineKeyboardMarkup(buttons) 152 | ) 153 | 154 | @Bot.on_message(filters.command('users') & filters.private & filters.user(ADMINS)) 155 | async def get_users(client: Bot, message: Message): 156 | msg = await client.send_message(chat_id=message.chat.id, text=WAIT_MSG) 157 | users = await full_userbase() 158 | await msg.edit(f"{len(users)} users are using this bot") 159 | 160 | @Bot.on_message(filters.private & filters.command('broadcast') & filters.user(ADMINS)) 161 | async def send_text(client: Bot, message: Message): 162 | if message.reply_to_message: 163 | query = await full_userbase() 164 | broadcast_msg = message.reply_to_message 165 | total = 0 166 | successful = 0 167 | blocked = 0 168 | deleted = 0 169 | unsuccessful = 0 170 | 171 | pls_wait = await message.reply("ʙʀᴏᴀᴅᴄᴀꜱᴛ ᴘʀᴏᴄᴇꜱꜱɪɴɢ....") 172 | for chat_id in query: 173 | try: 174 | await broadcast_msg.copy(chat_id) 175 | successful += 1 176 | except FloodWait as e: 177 | await asyncio.sleep(e.x) 178 | await broadcast_msg.copy(chat_id) 179 | successful += 1 180 | except UserIsBlocked: 181 | await del_user(chat_id) 182 | blocked += 1 183 | except InputUserDeactivated: 184 | await del_user(chat_id) 185 | deleted += 1 186 | except: 187 | unsuccessful += 1 188 | pass 189 | total += 1 190 | 191 | status = f"""ʙʀᴏᴀᴅᴄᴀꜱᴛ... 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(REPLY_ERROR) 203 | await asyncio.sleep(8) 204 | await msg.delete() 205 | -------------------------------------------------------------------------------- /plugins/start.py: -------------------------------------------------------------------------------- 1 | import os 2 | import asyncio 3 | from pyrogram import Client, filters 4 | from pyrogram.enums import ParseMode 5 | from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery 6 | from pyrogram.errors import FloodWait, UserIsBlocked, InputUserDeactivated 7 | 8 | from bot import Bot 9 | from config import * 10 | from helper_func import subscribed, encode, decode, get_messages 11 | from database.database import add_user, del_user, full_userbase, present_user 12 | 13 | 14 | @Bot.on_message(filters.command('start') & filters.private & subscribed) 15 | async def start_command(client: Client, message: Message): 16 | id = message.from_user.id 17 | if not await present_user(id): 18 | try: 19 | await add_user(id) 20 | except: 21 | pass 22 | text = message.text 23 | if len(text)>7: 24 | try: 25 | base64_string = text.split(" ", 1)[1] 26 | except: 27 | return 28 | string = await decode(base64_string) 29 | argument = string.split("-") 30 | if len(argument) == 3: 31 | try: 32 | start = int(int(argument[1]) / abs(client.db_channel.id)) 33 | end = int(int(argument[2]) / abs(client.db_channel.id)) 34 | except: 35 | return 36 | if start <= end: 37 | ids = range(start,end+1) 38 | else: 39 | ids = [] 40 | i = start 41 | while True: 42 | ids.append(i) 43 | i -= 1 44 | if i < end: 45 | break 46 | elif len(argument) == 2: 47 | try: 48 | ids = [int(int(argument[1]) / abs(client.db_channel.id))] 49 | except: 50 | return 51 | temp_msg = await message.reply("Wait Bro...") 52 | try: 53 | messages = await get_messages(client, ids) 54 | except: 55 | await message.reply_text("Something went wrong..!") 56 | return 57 | await temp_msg.delete() 58 | 59 | for msg in messages: 60 | 61 | if bool(CUSTOM_CAPTION) & bool(msg.document): 62 | caption = CUSTOM_CAPTION.format(previouscaption = "" if not msg.caption else msg.caption.html, filename = msg.document.file_name) 63 | else: 64 | caption = "" if not msg.caption else msg.caption.html 65 | 66 | if DISABLE_CHANNEL_BUTTON: 67 | reply_markup = msg.reply_markup 68 | else: 69 | reply_markup = None 70 | 71 | try: 72 | await msg.copy(chat_id=message.from_user.id, caption = caption, parse_mode = ParseMode.HTML, reply_markup = reply_markup, protect_content=PROTECT_CONTENT) 73 | await asyncio.sleep(1) 74 | except FloodWait as e: 75 | await asyncio.sleep(e.x) 76 | await msg.copy(chat_id=message.from_user.id, caption = caption, parse_mode = ParseMode.HTML, reply_markup = reply_markup, protect_content=PROTECT_CONTENT) 77 | except: 78 | pass 79 | return 80 | else: 81 | reply_markup = InlineKeyboardMarkup( 82 | [ 83 | [ InlineKeyboardButton(text="🏖️", callback_data="about"), 84 | InlineKeyboardButton(text="🍂", callback_data="about"), 85 | InlineKeyboardButton(text="⚠️", callback_data="me"), 86 | InlineKeyboardButton(text="💸", callback_data="about"), 87 | InlineKeyboardButton(text="🎭", callback_data="about"), 88 | ],[ InlineKeyboardButton( "ᴍᴀɪɴ ᴄʜᴀɴɴᴇʟ", callback_data = "main" ), 89 | InlineKeyboardButton("sᴏᴜʀᴄᴇ ᴄᴏᴅᴇ ", callback_data = "source") 90 | ], [ InlineKeyboardButton("ᴡᴀᴛᴄʜ sʜᴏʀᴛs ᴠɪᴅᴇᴏs", url = "http://t.me/UnseenRobot/shorts") ], 91 | [ 92 | InlineKeyboardButton("ʜᴇʟᴘ", callback_data = "help"), 93 | InlineKeyboardButton("ᴀʙᴏᴜᴛ", callback_data = "about") 94 | ] 95 | ] 96 | ) 97 | await message.reply_photo( 98 | photo= START_PIC, 99 | caption= START_MSG.format( 100 | first = message.from_user.first_name, 101 | last = message.from_user.last_name, 102 | username = None if not message.from_user.username else '@' + message.from_user.username, 103 | mention = message.from_user.mention, 104 | id = message.from_user.id 105 | ), 106 | reply_markup = reply_markup, 107 | 108 | ) 109 | return 110 | 111 | 112 | #=====================================================================================## 113 | 114 | WAIT_MSG = "Working...." 115 | 116 | REPLY_ERROR = "Use this command as a reply to any telegram message without any spaces." 117 | 118 | #=====================================================================================## 119 | 120 | 121 | 122 | @Bot.on_message(filters.command('start') & filters.private) 123 | async def not_joined(client: Client, message: Message): 124 | buttons = [ 125 | [ 126 | InlineKeyboardButton(text="• ᴊᴏɪɴ ᴄʜᴀɴɴᴇʟ", url=client.invitelink), 127 | InlineKeyboardButton(text="ᴊᴏɪɴ ᴄʜᴀɴɴᴇʟ •", url=client.invitelink2), 128 | ] 129 | ] 130 | try: 131 | buttons.append( 132 | [ 133 | InlineKeyboardButton( 134 | text='• ᴛʀʏ ᴀɢᴀɪɴ •', 135 | url=f"https://t.me/{client.username}?start={message.command[1]}" 136 | ) 137 | ] 138 | ) 139 | except IndexError: 140 | pass 141 | 142 | await message.reply_photo( 143 | photo=FORCE_PIC, 144 | caption=FORCE_MSG.format( 145 | first=message.from_user.first_name, 146 | last=message.from_user.last_name, 147 | username=None if not message.from_user.username else '@' + message.from_user.username, 148 | mention=message.from_user.mention, 149 | id=message.from_user.id 150 | ), 151 | reply_markup=InlineKeyboardMarkup(buttons) 152 | ) 153 | 154 | @Bot.on_message(filters.command('users') & filters.private & filters.user(ADMINS)) 155 | async def get_users(client: Bot, message: Message): 156 | msg = await client.send_message(chat_id=message.chat.id, text=WAIT_MSG) 157 | users = await full_userbase() 158 | await msg.edit(f"{len(users)} users are using this bot") 159 | 160 | @Bot.on_message(filters.private & filters.command('broadcast') & filters.user(ADMINS)) 161 | async def send_text(client: Bot, message: Message): 162 | if message.reply_to_message: 163 | query = await full_userbase() 164 | broadcast_msg = message.reply_to_message 165 | total = 0 166 | successful = 0 167 | blocked = 0 168 | deleted = 0 169 | unsuccessful = 0 170 | 171 | pls_wait = await message.reply("ʙʀᴏᴀᴅᴄᴀꜱᴛ ᴘʀᴏᴄᴇꜱꜱɪɴɢ....") 172 | for chat_id in query: 173 | try: 174 | await broadcast_msg.copy(chat_id) 175 | successful += 1 176 | except FloodWait as e: 177 | await asyncio.sleep(e.x) 178 | await broadcast_msg.copy(chat_id) 179 | successful += 1 180 | except UserIsBlocked: 181 | await del_user(chat_id) 182 | blocked += 1 183 | except InputUserDeactivated: 184 | await del_user(chat_id) 185 | deleted += 1 186 | except: 187 | unsuccessful += 1 188 | pass 189 | total += 1 190 | 191 | status = f"""ʙʀᴏᴀᴅᴄᴀꜱᴛ... 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(REPLY_ERROR) 203 | await asyncio.sleep(8) 204 | await msg.delete() 205 | --------------------------------------------------------------------------------