├── .github └── workflows │ └── codeql-analysis.yml ├── Dockerfile ├── Procfile ├── README.md ├── app.json ├── bot.py ├── configs.py ├── handlers ├── README.md ├── add_user_to_db.py ├── broadcast_handlers.py ├── check_user_status.py ├── database.py ├── force_sub_handler.py ├── helpers.py ├── save_media.py └── send_file.py ├── heroku.yml ├── render.yaml └── requirements.txt /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | schedule: 21 | - cron: '28 2 * * 2' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'python' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v1 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v1 72 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | 3 | ENV DEBIAN_FRONTEND=noninteractive 4 | RUN apt-get update 5 | RUN echo y | apt-get install locales 6 | RUN echo y | apt install build-essential 7 | RUN apt -qq install -y --no-install-recommends \ 8 | curl \ 9 | git \ 10 | gnupg2 \ 11 | wget \ 12 | 13 | RUN set -ex; \ 14 | apt-get update \ 15 | && apt-get install -y --no-install-recommends \ 16 | busybox \ 17 | git \ 18 | python3 \ 19 | python3-dev \ 20 | python3-pip \ 21 | python3-lxml \ 22 | pv \ 23 | && apt-get autoclean \ 24 | && apt-get autoremove \ 25 | && rm -rf /var/lib/apt/lists/* 26 | 27 | RUN pip3 install setuptools wheel yarl multidict 28 | COPY requirements.txt . 29 | RUN pip3 install -r requirements.txt 30 | RUN dpkg-reconfigure locales 31 | COPY . /app 32 | 33 | CMD ["python3", "bot.py"] 34 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: python3 bot.py 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![TGFileStore](https://telegra.ph/file/d651c7b7943a9702f846d.png) 2 | 3 | ⍟ 𝗧𝗵𝗶𝘀 𝗶𝘀 𝗧𝗲𝗹𝗲𝗴𝗿𝗮𝗺 𝗣𝗮𝗿𝗺𝗮𝗻𝗲𝗻𝘁 𝗙𝗶𝗹𝗲𝘀 𝗦𝘁𝗼𝗿𝗲 𝗕𝗼𝘁 𝗯𝘆 [@TeleRoidGroup](https://telegram.dog/OwnYourBotz). 4 | 5 | * **Language:** [Python3](https://www.python.org) 6 | * **Library:** [Pyrogram](https://docs.pyrogram.org) 7 | 8 | ### Features: 9 | - In PM Just Forward or Send any file it will save on Database & give you the Access Link. 10 | - In Channel Add Bot as Admin with Edit Rights. When you will send any file or media in Channel it will Edit the Broadcast Message with Saved Link Button. 11 | - You can also Broadcast anythings via this Bot. 12 | - You can also Do Force Sub to a Channel to allow access the Bot. 13 | 14 | ### Demo Bot: 15 | 16 | 17 | ![Configs](https://telegra.ph/file/033408792afc4d4f1f8f6.png) 🤖 18 | 19 | - `API_ID` - Get this from [@TeleORG_Bot](https://t.me/TeleORG_Bot) 20 | - `API_HASH` - Get this from [@TeleORG_Bot](https://t.me/TeleORG_Bot) 21 | - `BOT_TOKEN` - Get this from [@BotFather](https://t.me/BotFather) 22 | - `BOT_USERNAME` - You Bot Username. *(Without [@])* 23 | - `DB_CHANNEL` - A Telegram Channel ID. 24 | - Make a Channel for Storing Files. We will use that as Database. Channel must be Private! Else you will be Copyright by [Telegram DMCA](https://t.me/dmcatelegram)! 25 | - `BOT_OWNER` - Bot Owner UserID 26 | - Put your Telegram UserID for doing Broadcast. 27 | - `DATABASE_URL` - MongoDB Database URI 28 | - This for Saving UserIDs. When you will Broadcast, bot will forward the Broadcast to DB Users. 29 | - `UPDATES_CHANNEL` - Force Sub Channel ID *(Optional)* 30 | - ID of a Channel which you want to do Force Sub to use the bot. 31 | - `LOG_CHANNEL` - Logs Channel ID 32 | - This for some getting user info. If any new User added to DB, Bot will send Log to that Logs Channel. You can use same DB Channel ID. 33 | 34 | ### Deploy Now: 35 | [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/PredatorHackerzZ/TG-FileStore/tree/shortner) 36 | 37 | ## Commands: 38 | ``` 39 | start - start the bot 40 | clear_batch - Clear User Batch Files 41 | status - Show number of users in DB [Owner Only] 42 | broadcast - Broadcast replied message to DB Users [Owner Only] 43 | ban_user - [user_id] [ban_duration] [ban_reason] Ban Any User [Owner Only] 44 | unban_user - [user_id] Unban Any User [Owner Only] 45 | banned_users - Get All Banned Users [Owner Only] 46 | ``` 47 | 48 | ### 𝐒𝐮𝐩𝐩𝐨𝐫𝐭 𝐆𝐫𝐨𝐮𝐩: 49 | 50 | ### 𝐔𝐩𝐝𝐚𝐭𝐞𝐬 𝐂𝐡𝐚𝐧𝐧𝐞𝐥: 51 | 52 | 53 | 54 | 👲 DEV 55 | 56 |

57 |
58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "File Store Bot", 3 | "description": "A Telegram Files Store Bot to protect your Files in Pyrogram by @MrAbhi2k3 as Shortener", 4 | "keywords": [ 5 | "telegram", 6 | "files", 7 | "store", 8 | "bot" 9 | ], 10 | "repository": "https://github.com/PredatorHackerzZ/TG-FileStore", 11 | "website": "https://telegram.me/TeleRoidGroup", 12 | "success_url": "https://t.me/TeleRoidGroup", 13 | "logo": "https://telegra.ph/file/b39906f572822b3ab82c8.jpg", 14 | "env": { 15 | "API_ID": { 16 | "description": "Get this value from my.telegram.org" 17 | }, 18 | "API_HASH": { 19 | "description": "Get this value from my.telegram.org" 20 | }, 21 | "BOT_TOKEN": { 22 | "description": "Get this from @BotFather the Official Bot" 23 | }, 24 | "BOT_USERNAME": { 25 | "description": "Your Bot Username which you sent to @BotFather (Without [@])" 26 | }, 27 | "DB_CHANNEL": { 28 | "description": "The Channel ID which will be used as Database. Example: -100123456789" 29 | }, 30 | "BOT_OWNER": { 31 | "description": "Bot Owner UserID" 32 | }, 33 | "DATABASE_URL": { 34 | "description": "MongoDB Database URI for Saving UserID for Broadcast." 35 | }, 36 | "UPDATES_CHANNEL": { 37 | "description": "ID of a Channel which you want to do Force Sub to use the bot. Example: -100123456789", 38 | "required": false 39 | }, 40 | "OTHER_USERS_CAN_SAVE_FILE": { 41 | "description": "Id of those users You want to allow to Save Files" 42 | }, 43 | "SHORTLINK_URL": { 44 | "description": "Shortlink Domain URL To Use it to short Links. Example: tnshort.net" 45 | }, 46 | "SHORTLINK_API": { 47 | "description": "Shortlink API To Use it to short Links. Example: tnsh45ort123shor6789" 48 | }, 49 | "LOG_CHANNEL": { 50 | "description": "Logs Channel ID for some Tracking XD. Example: -100123456789" 51 | } 52 | }, 53 | "buildpacks": [ 54 | { 55 | "url": "heroku/python" 56 | } 57 | ], 58 | "formation": { 59 | "worker": { 60 | "quantity": 1, 61 | "size": "eco" 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /bot.py: -------------------------------------------------------------------------------- 1 | # (c) @TeleRoidGroup || @PredatorHackerzZ 2 | 3 | import os 4 | import asyncio 5 | import traceback 6 | from binascii import ( 7 | Error 8 | ) 9 | from pyrogram import ( 10 | Client, 11 | enums, 12 | filters 13 | ) 14 | from pyrogram.errors import ( 15 | UserNotParticipant, 16 | FloodWait, 17 | QueryIdInvalid 18 | ) 19 | from pyrogram.types import ( 20 | InlineKeyboardMarkup, 21 | InlineKeyboardButton, 22 | CallbackQuery, 23 | Message 24 | ) 25 | from configs import Config 26 | from handlers.database import db 27 | from handlers.add_user_to_db import add_user_to_database 28 | from handlers.send_file import send_media_and_reply 29 | from handlers.helpers import b64_to_str, str_to_b64 30 | from handlers.check_user_status import handle_user_status 31 | from handlers.force_sub_handler import ( 32 | handle_force_sub, 33 | get_invite_link 34 | ) 35 | from handlers.broadcast_handlers import main_broadcast_handler 36 | from handlers.save_media import ( 37 | save_media_in_channel, 38 | save_batch_media_in_channel 39 | ) 40 | 41 | MediaList = {} 42 | 43 | Bot = Client( 44 | name=Config.BOT_USERNAME, 45 | in_memory=True, 46 | bot_token=Config.BOT_TOKEN, 47 | api_id=Config.API_ID, 48 | api_hash=Config.API_HASH 49 | ) 50 | 51 | 52 | @Bot.on_message(filters.private) 53 | async def _(bot: Client, cmd: Message): 54 | await handle_user_status(bot, cmd) 55 | 56 | 57 | @Bot.on_message(filters.command("start") & filters.private) 58 | async def start(bot: Client, cmd: Message): 59 | 60 | if cmd.from_user.id in Config.BANNED_USERS: 61 | await cmd.reply_text("Sorry, You are banned.") 62 | return 63 | if Config.UPDATES_CHANNEL is not None: 64 | back = await handle_force_sub(bot, cmd) 65 | if back == 400: 66 | return 67 | 68 | usr_cmd = cmd.text.split("_", 1)[-1] 69 | if usr_cmd == "/start": 70 | await add_user_to_database(bot, cmd) 71 | await cmd.reply_text( 72 | Config.HOME_TEXT.format(cmd.from_user.first_name, cmd.from_user.id), 73 | disable_web_page_preview=True, 74 | reply_markup=InlineKeyboardMarkup( 75 | [ 76 | [ 77 | InlineKeyboardButton("BotsList Channel", url="https://t.me/TGRobot_List") 78 | ], 79 | [ 80 | InlineKeyboardButton("About Bot", callback_data="aboutbot"), 81 | InlineKeyboardButton("About Dev", callback_data="aboutdevs"), 82 | InlineKeyboardButton("Close 🚪", callback_data="closeMessage") 83 | ], 84 | [ 85 | InlineKeyboardButton("Bots Channel", url="https://t.me/TeleRoidGroup"), 86 | InlineKeyboardButton(" Support Group", url="https://t.me/TeleRoid14") 87 | ] 88 | ] 89 | ) 90 | ) 91 | else: 92 | try: 93 | try: 94 | file_id = int(b64_to_str(usr_cmd).split("_")[-1]) 95 | except (Error, UnicodeDecodeError): 96 | file_id = int(usr_cmd.split("_")[-1]) 97 | GetMessage = await bot.get_messages(chat_id=Config.DB_CHANNEL, message_ids=file_id) 98 | message_ids = [] 99 | if GetMessage.text: 100 | message_ids = GetMessage.text.split(" ") 101 | _response_msg = await cmd.reply_text( 102 | text=f"**Total Files:** `{len(message_ids)}`", 103 | quote=True, 104 | disable_web_page_preview=True 105 | ) 106 | else: 107 | message_ids.append(int(GetMessage.id)) 108 | for i in range(len(message_ids)): 109 | await send_media_and_reply(bot, user_id=cmd.from_user.id, file_id=int(message_ids[i])) 110 | except Exception as err: 111 | await cmd.reply_text(f"Something went wrong!\n\n**Error:** `{err}`") 112 | 113 | 114 | @Bot.on_message((filters.document | filters.video | filters.audio | filters.photo) & ~filters.chat(Config.DB_CHANNEL)) 115 | async def main(bot: Client, message: Message): 116 | 117 | if message.chat.type == enums.ChatType.PRIVATE: 118 | 119 | await add_user_to_database(bot, message) 120 | 121 | if Config.UPDATES_CHANNEL is not None: 122 | back = await handle_force_sub(bot, message) 123 | if back == 400: 124 | return 125 | 126 | if message.from_user.id in Config.BANNED_USERS: 127 | await message.reply_text("Sorry, You are banned!\n\nContact [Support Group](https://t.me/TeleRoid14)", 128 | disable_web_page_preview=True) 129 | return 130 | 131 | if Config.OTHER_USERS_CAN_SAVE_FILE is False: 132 | return 133 | 134 | await message.reply_text( 135 | text="**Choose an option from below:**", 136 | reply_markup=InlineKeyboardMarkup([ 137 | [InlineKeyboardButton("Save in Batch", callback_data="addToBatchTrue")], 138 | [InlineKeyboardButton("Get Sharable Link", callback_data="addToBatchFalse")] 139 | ]), 140 | quote=True, 141 | disable_web_page_preview=True 142 | ) 143 | elif message.chat.type == enums.ChatType.CHANNEL: 144 | if (message.chat.id == int(Config.LOG_CHANNEL)) or (message.chat.id == int(Config.UPDATES_CHANNEL)) or message.forward_from_chat or message.forward_from: 145 | return 146 | elif int(message.chat.id) in Config.BANNED_CHAT_IDS: 147 | await bot.leave_chat(message.chat.id) 148 | return 149 | else: 150 | pass 151 | 152 | try: 153 | forwarded_msg = await message.forward(Config.DB_CHANNEL) 154 | file_er_id = str(forwarded_msg.id) 155 | share_link = f"https://t.me/{Config.BOT_USERNAME}?start=PredatorHackerzZ_{str_to_b64(file_er_id)}" 156 | CH_edit = await bot.edit_message_reply_markup(message.chat.id, message.id, 157 | reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton( 158 | "Get Sharable Link", url=share_link)]])) 159 | if message.chat.username: 160 | await forwarded_msg.reply_text( 161 | f"#CHANNEL_BUTTON:\n\n[{message.chat.title}](https://t.me/{message.chat.username}/{CH_edit.id}) Channel's Broadcasted File's Button Added!") 162 | else: 163 | private_ch = str(message.chat.id)[4:] 164 | await forwarded_msg.reply_text( 165 | f"#CHANNEL_BUTTON:\n\n[{message.chat.title}](https://t.me/c/{private_ch}/{CH_edit.id}) Channel's Broadcasted File's Button Added!") 166 | except FloodWait as sl: 167 | await asyncio.sleep(sl.value) 168 | await bot.send_message( 169 | chat_id=int(Config.LOG_CHANNEL), 170 | text=f"#FloodWait:\nGot FloodWait of `{str(sl.value)}s` from `{str(message.chat.id)}` !!", 171 | disable_web_page_preview=True 172 | ) 173 | except Exception as err: 174 | await bot.leave_chat(message.chat.id) 175 | await bot.send_message( 176 | chat_id=int(Config.LOG_CHANNEL), 177 | text=f"#ERROR_TRACEBACK:\nGot Error from `{str(message.chat.id)}` !!\n\n**Traceback:** `{err}`", 178 | disable_web_page_preview=True 179 | ) 180 | 181 | 182 | @Bot.on_message(filters.private & filters.command("broadcast") & filters.user(Config.BOT_OWNER) & filters.reply) 183 | async def broadcast_handler_open(_, m: Message): 184 | await main_broadcast_handler(m, db) 185 | 186 | 187 | @Bot.on_message(filters.private & filters.command("status") & filters.user(Config.BOT_OWNER)) 188 | async def sts(_, m: Message): 189 | total_users = await db.total_users_count() 190 | await m.reply_text( 191 | text=f"**Total Users in DB:** `{total_users}`", 192 | quote=True 193 | ) 194 | 195 | 196 | @Bot.on_message(filters.private & filters.command("ban_user") & filters.user(Config.BOT_OWNER)) 197 | async def ban(c: Client, m: Message): 198 | 199 | if len(m.command) == 1: 200 | await m.reply_text( 201 | f"Use this command to ban any user from the bot.\n\n" 202 | f"Usage:\n\n" 203 | f"`/ban_user user_id ban_duration ban_reason`\n\n" 204 | f"Eg: `/ban_user 1234567 28 You misused me.`\n" 205 | f"This will ban user with id `1234567` for `28` days for the reason `You misused me`.", 206 | quote=True 207 | ) 208 | return 209 | 210 | try: 211 | user_id = int(m.command[1]) 212 | ban_duration = int(m.command[2]) 213 | ban_reason = ' '.join(m.command[3:]) 214 | ban_log_text = f"Banning user {user_id} for {ban_duration} days for the reason {ban_reason}." 215 | try: 216 | await c.send_message( 217 | user_id, 218 | f"You are banned to use this bot for **{ban_duration}** day(s) for the reason __{ban_reason}__ \n\n" 219 | f"**Message from the admin**" 220 | ) 221 | ban_log_text += '\n\nUser notified successfully!' 222 | except: 223 | traceback.print_exc() 224 | ban_log_text += f"\n\nUser notification failed! \n\n`{traceback.format_exc()}`" 225 | 226 | await db.ban_user(user_id, ban_duration, ban_reason) 227 | print(ban_log_text) 228 | await m.reply_text( 229 | ban_log_text, 230 | quote=True 231 | ) 232 | except: 233 | traceback.print_exc() 234 | await m.reply_text( 235 | f"Error occoured! Traceback given below\n\n`{traceback.format_exc()}`", 236 | quote=True 237 | ) 238 | 239 | 240 | @Bot.on_message(filters.private & filters.command("unban_user") & filters.user(Config.BOT_OWNER)) 241 | async def unban(c: Client, m: Message): 242 | 243 | if len(m.command) == 1: 244 | await m.reply_text( 245 | f"Use this command to unban any user.\n\n" 246 | f"Usage:\n\n`/unban_user user_id`\n\n" 247 | f"Eg: `/unban_user 1234567`\n" 248 | f"This will unban user with id `1234567`.", 249 | quote=True 250 | ) 251 | return 252 | 253 | try: 254 | user_id = int(m.command[1]) 255 | unban_log_text = f"Unbanning user {user_id}" 256 | try: 257 | await c.send_message( 258 | user_id, 259 | f"Your ban was lifted!" 260 | ) 261 | unban_log_text += '\n\nUser notified successfully!' 262 | except: 263 | traceback.print_exc() 264 | unban_log_text += f"\n\nUser notification failed! \n\n`{traceback.format_exc()}`" 265 | await db.remove_ban(user_id) 266 | print(unban_log_text) 267 | await m.reply_text( 268 | unban_log_text, 269 | quote=True 270 | ) 271 | except: 272 | traceback.print_exc() 273 | await m.reply_text( 274 | f"Error occurred! Traceback given below\n\n`{traceback.format_exc()}`", 275 | quote=True 276 | ) 277 | 278 | 279 | @Bot.on_message(filters.private & filters.command("banned_users") & filters.user(Config.BOT_OWNER)) 280 | async def _banned_users(_, m: Message): 281 | 282 | all_banned_users = await db.get_all_banned_users() 283 | banned_usr_count = 0 284 | text = '' 285 | 286 | async for banned_user in all_banned_users: 287 | user_id = banned_user['id'] 288 | ban_duration = banned_user['ban_status']['ban_duration'] 289 | banned_on = banned_user['ban_status']['banned_on'] 290 | ban_reason = banned_user['ban_status']['ban_reason'] 291 | banned_usr_count += 1 292 | text += f"> **user_id**: `{user_id}`, **Ban Duration**: `{ban_duration}`, " \ 293 | f"**Banned on**: `{banned_on}`, **Reason**: `{ban_reason}`\n\n" 294 | reply_text = f"Total banned user(s): `{banned_usr_count}`\n\n{text}" 295 | if len(reply_text) > 4096: 296 | with open('banned-users.txt', 'w') as f: 297 | f.write(reply_text) 298 | await m.reply_document('banned-users.txt', True) 299 | os.remove('banned-users.txt') 300 | return 301 | await m.reply_text(reply_text, True) 302 | 303 | 304 | @Bot.on_message(filters.private & filters.command("clear_batch")) 305 | async def clear_user_batch(bot: Client, m: Message): 306 | MediaList[f"{str(m.from_user.id)}"] = [] 307 | await m.reply_text("Cleared your batch files successfully!") 308 | 309 | 310 | @Bot.on_callback_query() 311 | async def button(bot: Client, cmd: CallbackQuery): 312 | 313 | cb_data = cmd.data 314 | if "aboutbot" in cb_data: 315 | await cmd.message.edit( 316 | Config.ABOUT_BOT_TEXT, 317 | disable_web_page_preview=True, 318 | reply_markup=InlineKeyboardMarkup( 319 | [ 320 | [ 321 | InlineKeyboardButton("Source Codes of Bot", 322 | url="https://github.com/PredatorHackerzZ/TG-FileStore") 323 | ], 324 | [ 325 | InlineKeyboardButton("Go Home", callback_data="gotohome"), 326 | InlineKeyboardButton("About Dev", callback_data="aboutdevs") 327 | ] 328 | ] 329 | ) 330 | ) 331 | 332 | elif "aboutdevs" in cb_data: 333 | await cmd.message.edit( 334 | Config.ABOUT_DEV_TEXT, 335 | disable_web_page_preview=True, 336 | reply_markup=InlineKeyboardMarkup( 337 | [ 338 | [ 339 | InlineKeyboardButton("Source Codes of Bot", 340 | url="https://github.com/PredatorHackerzZ/TG-FileStore") 341 | ], 342 | [ 343 | InlineKeyboardButton("About Bot", callback_data="aboutbot"), 344 | InlineKeyboardButton("Go Home", callback_data="gotohome") 345 | ] 346 | ] 347 | ) 348 | ) 349 | 350 | elif "gotohome" in cb_data: 351 | await cmd.message.edit( 352 | Config.HOME_TEXT.format(cmd.message.chat.first_name, cmd.message.chat.id), 353 | disable_web_page_preview=True, 354 | reply_markup=InlineKeyboardMarkup( 355 | [ 356 | [ 357 | InlineKeyboardButton("BotsList Channel", url="https://t.me/PayForBotz") 358 | ], 359 | [ 360 | InlineKeyboardButton("About Bot", callback_data="aboutbot"), 361 | InlineKeyboardButton("About Dev", callback_data="aboutdevs"), 362 | InlineKeyboardButton("Close 🚪", callback_data="closeMessage") 363 | ], 364 | [ 365 | InlineKeyboardButton("Support Group", url="https://t.me/TeleRoid14"), 366 | InlineKeyboardButton("Bots Channel", url="https://t.me/TeleRoidGroup") 367 | ] 368 | ] 369 | ) 370 | ) 371 | 372 | elif "refreshForceSub" in cb_data: 373 | if Config.UPDATES_CHANNEL: 374 | if Config.UPDATES_CHANNEL.startswith("-100"): 375 | channel_chat_id = int(Config.UPDATES_CHANNEL) 376 | else: 377 | channel_chat_id = Config.UPDATES_CHANNEL 378 | try: 379 | user = await bot.get_chat_member(channel_chat_id, cmd.message.chat.id) 380 | if user.status == "kicked": 381 | await cmd.message.edit( 382 | text="Sorry Sir, You are Banned to use me. Contact my [Support Group](https://t.me/TeleRoid14).", 383 | disable_web_page_preview=True 384 | ) 385 | return 386 | except UserNotParticipant: 387 | invite_link = await get_invite_link(channel_chat_id) 388 | await cmd.message.edit( 389 | text="**I like Your Smartness But Don't Be Oversmart! 😑**\n\n", 390 | reply_markup=InlineKeyboardMarkup( 391 | [ 392 | [ 393 | InlineKeyboardButton("🤖 Join Updates Channel", url=invite_link.invite_link) 394 | ], 395 | [ 396 | InlineKeyboardButton("🔄 Refresh 🔄", callback_data="refreshmeh") 397 | ] 398 | ] 399 | ) 400 | ) 401 | return 402 | except Exception: 403 | await cmd.message.edit( 404 | text="Something went Wrong. Contact my [Support Group](https://t.me/TeleRoid14).", 405 | disable_web_page_preview=True 406 | ) 407 | return 408 | await cmd.message.edit( 409 | text=Config.HOME_TEXT.format(cmd.message.chat.first_name, cmd.message.chat.id), 410 | disable_web_page_preview=True, 411 | reply_markup=InlineKeyboardMarkup( 412 | [ 413 | [ 414 | InlineKeyboardButton("Support Group", url="https://t.me/TeleRoid14"), 415 | InlineKeyboardButton("Bots Channel", url="https://t.me/TeleRoidGroup") 416 | ], 417 | [ 418 | InlineKeyboardButton("About Bot", callback_data="aboutbot"), 419 | InlineKeyboardButton("About Dev", callback_data="aboutdevs") 420 | ] 421 | ] 422 | ) 423 | ) 424 | 425 | elif cb_data.startswith("ban_user_"): 426 | user_id = cb_data.split("_", 2)[-1] 427 | if Config.UPDATES_CHANNEL is None: 428 | await cmd.answer("Sorry Sir, You didn't Set any Updates Channel!", show_alert=True) 429 | return 430 | if not int(cmd.from_user.id) == Config.BOT_OWNER: 431 | await cmd.answer("You are not allowed to do that!", show_alert=True) 432 | return 433 | try: 434 | await bot.kick_chat_member(chat_id=int(Config.UPDATES_CHANNEL), user_id=int(user_id)) 435 | await cmd.answer("User Banned from Updates Channel!", show_alert=True) 436 | except Exception as e: 437 | await cmd.answer(f"Can't Ban Him!\n\nError: {e}", show_alert=True) 438 | 439 | elif "addToBatchTrue" in cb_data: 440 | if MediaList.get(f"{str(cmd.from_user.id)}", None) is None: 441 | MediaList[f"{str(cmd.from_user.id)}"] = [] 442 | file_id = cmd.message.reply_to_message.id 443 | MediaList[f"{str(cmd.from_user.id)}"].append(file_id) 444 | await cmd.message.edit("File Saved in Batch!\n\n" 445 | "Press below button to get batch link.", 446 | reply_markup=InlineKeyboardMarkup([ 447 | [InlineKeyboardButton("Get Batch Link", callback_data="getBatchLink")], 448 | [InlineKeyboardButton("Close Message", callback_data="closeMessage")] 449 | ])) 450 | 451 | elif "addToBatchFalse" in cb_data: 452 | await save_media_in_channel(bot, editable=cmd.message, message=cmd.message.reply_to_message) 453 | 454 | elif "getBatchLink" in cb_data: 455 | message_ids = MediaList.get(f"{str(cmd.from_user.id)}", None) 456 | if message_ids is None: 457 | await cmd.answer("Batch List Empty!", show_alert=True) 458 | return 459 | await cmd.message.edit("Please wait, generating batch link ...") 460 | await save_batch_media_in_channel(bot=bot, editable=cmd.message, message_ids=message_ids) 461 | MediaList[f"{str(cmd.from_user.id)}"] = [] 462 | 463 | elif "closeMessage" in cb_data: 464 | await cmd.message.delete(True) 465 | 466 | try: 467 | await cmd.answer() 468 | except QueryIdInvalid: pass 469 | 470 | 471 | Bot.run() 472 | -------------------------------------------------------------------------------- /configs.py: -------------------------------------------------------------------------------- 1 | # (c) @PredatorHackerzZ || @TeleRoidGroup 2 | 3 | import os 4 | 5 | class Config(object): 6 | API_ID = int(os.environ.get("API_ID", "0")) 7 | API_HASH = os.environ.get("API_HASH") 8 | BOT_TOKEN = os.environ.get("BOT_TOKEN") 9 | BOT_USERNAME = os.environ.get("BOT_USERNAME") 10 | DB_CHANNEL = int(os.environ.get("DB_CHANNEL", "-100")) 11 | SHORTLINK_URL = os.environ.get('SHORTLINK_URL') 12 | SHORTLINK_API = os.environ.get('SHORTLINK_API') 13 | BOT_OWNER = int(os.environ.get("BOT_OWNER", "1445283714")) 14 | DATABASE_URL = os.environ.get("DATABASE_URL") 15 | UPDATES_CHANNEL = os.environ.get("UPDATES_CHANNEL", "") 16 | LOG_CHANNEL = os.environ.get("LOG_CHANNEL", None) 17 | BANNED_USERS = set(int(x) for x in os.environ.get("BANNED_USERS", "1234567890").split()) 18 | FORWARD_AS_COPY = bool(os.environ.get("FORWARD_AS_COPY", True)) 19 | BROADCAST_AS_COPY = bool(os.environ.get("BROADCAST_AS_COPY", False)) 20 | BANNED_CHAT_IDS = list(set(int(x) for x in os.environ.get("BANNED_CHAT_IDS", "-1001362659779 -1001255795497").split())) 21 | OTHER_USERS_CAN_SAVE_FILE = [int(id) for id in os.environ.get("OTHER_USERS_CAN_SAVE_FILE", "").split(",") if id.strip()] 22 | ABOUT_BOT_TEXT = f""" 23 | This is a Permanent FileStore Bot. 24 | Send Me any Media or File. I can Work In Channel too. Add Me to Channel with Edit Permission, I will add save Uploaded File in Channel and Share a Shareable Link. 25 | 26 | ╭────[ **🔅FɪʟᴇSᴛᴏʀᴇBᴏᴛ🔅**]────⍟ 27 | │ 28 | ├🔸 **My Name:** [FileStore Bot](https://t.me/{BOT_USERNAME}) 29 | │ 30 | ├🔸 **Language:** [Python 3](https://www.python.org) 31 | │ 32 | ├🔹 **Library:** [Pyrogram](https://docs.pyrogram.org) 33 | │ 34 | ├🔹 **Hosted On:** [Heroku](https://heroku.com) 35 | │ 36 | ├🔸 **Developer:** [Predator HackerzZ](https://t.me/OwnYourBotz) 37 | │ 38 | ├🔹 **Bot Support:** [Support Group](https://t.me/TeleRoid14) 39 | │ 40 | ├🔸 **Bot Updates:** [Bots Channel](https://t.me/TeleRoidGroup) 41 | │ 42 | ╰──────[ 😎 ]───────────⍟ 43 | """ 44 | ABOUT_DEV_TEXT = f""" 45 | 🧑🏻‍💻 **𝗗𝗲𝘃𝗲𝗹𝗼𝗽𝗲𝗿:** [@PredatorHackerzZ](https://github.com/PredatorHackerzZ) 46 | 47 | I am Super noob Please Support My Hard Work. 48 | 49 | [Donate Me](https://t.me/DonateXrobot) or ```teleroidgroup@axl``` 50 | """ 51 | HOME_TEXT = """ 52 | Hello, [{}](tg://user?id={})\n\nThis is a Permanent **FileStore Bot**. 53 | 54 | How to Use Bot & it's Benefits?? 55 | 56 | 📢 Send me any File & It will be uploaded in My Database & You will Get the File Link. 57 | 58 | ⚠️ Benefits: If you have a TeleGram Movie Channel or Any Copyright Channel, Then Its Useful for Daily Usage, You can Send Me Your File & I will Send Permanent Link to You & Channel will be Safe from **CopyRight Infringement** Issue. I support Channel Also You Can Check **About Bot**. 59 | 60 | ❌ **PORNOGRAPHY CONTENTS** are strictly prohibited & get Permanent Ban. 61 | """ 62 | -------------------------------------------------------------------------------- /handlers/README.md: -------------------------------------------------------------------------------- 1 | ### Botz By [@PredatorHackerzZ](https://t.me/TheTeleRoid) 2 | 3 | # Bots new Version 4 | 5 | ### Special Thanks @AbirHasan2005 6 | 7 | # Added With Batch Mode and Ban/Unban Command 8 | ° Features New Version Of Python And Modules 9 | 10 | ## € Thanks To Me By Sponsoring My Any Github Repo 11 | 12 | -------------------------------------------------------------------------------- /handlers/add_user_to_db.py: -------------------------------------------------------------------------------- 1 | # (c) @PredatorHackerzZ 2 | 3 | from configs import Config 4 | from handlers.database import db 5 | from pyrogram import Client 6 | from pyrogram.types import Message 7 | 8 | 9 | async def add_user_to_database(bot: Client, cmd: Message): 10 | if not await db.is_user_exist(cmd.from_user.id): 11 | await db.add_user(cmd.from_user.id) 12 | if Config.LOG_CHANNEL is not None: 13 | await bot.send_message( 14 | int(Config.LOG_CHANNEL), 15 | f"#NEW_USER: \n\nNew User [{cmd.from_user.first_name}](tg://user?id={cmd.from_user.id}) started @{Config.BOT_USERNAME} !!" 16 | ) 17 | -------------------------------------------------------------------------------- /handlers/broadcast_handlers.py: -------------------------------------------------------------------------------- 1 | # (c) @PredatorHackerzZ 2 | 3 | import time 4 | import string 5 | import random 6 | import datetime 7 | import aiofiles 8 | import asyncio 9 | import traceback 10 | import aiofiles.os 11 | from configs import Config 12 | from pyrogram.errors import ( 13 | FloodWait, 14 | InputUserDeactivated, 15 | UserIsBlocked, 16 | PeerIdInvalid 17 | ) 18 | 19 | broadcast_ids = {} 20 | 21 | 22 | async def send_msg(user_id, message): 23 | try: 24 | if Config.BROADCAST_AS_COPY is False: 25 | await message.forward(chat_id=user_id) 26 | elif Config.BROADCAST_AS_COPY is True: 27 | await message.copy(chat_id=user_id) 28 | return 200, None 29 | except FloodWait as e: 30 | await asyncio.sleep(e.value) 31 | return send_msg(user_id, message) 32 | except InputUserDeactivated: 33 | return 400, f"{user_id} : deactivated\n" 34 | except UserIsBlocked: 35 | return 400, f"{user_id} : blocked the bot\n" 36 | except PeerIdInvalid: 37 | return 400, f"{user_id} : user id invalid\n" 38 | except Exception as e: 39 | return 500, f"{user_id} : {traceback.format_exc()}\n" 40 | 41 | 42 | async def main_broadcast_handler(m, db): 43 | all_users = await db.get_all_users() 44 | broadcast_msg = m.reply_to_message 45 | while True: 46 | broadcast_id = ''.join([random.choice(string.ascii_letters) for i in range(3)]) 47 | if not broadcast_ids.get(broadcast_id): 48 | break 49 | out = await m.reply_text( 50 | text=f"Broadcast Started! You will be notified with log file when all the users are notified." 51 | ) 52 | start_time = time.time() 53 | total_users = await db.total_users_count() 54 | done = 0 55 | failed = 0 56 | success = 0 57 | broadcast_ids[broadcast_id] = dict( 58 | total=total_users, 59 | current=done, 60 | failed=failed, 61 | success=success 62 | ) 63 | async with aiofiles.open('broadcast.txt', 'w') as broadcast_log_file: 64 | async for user in all_users: 65 | sts, msg = await send_msg( 66 | user_id=int(user['id']), 67 | message=broadcast_msg 68 | ) 69 | if msg is not None: 70 | await broadcast_log_file.write(msg) 71 | if sts == 200: 72 | success += 1 73 | else: 74 | failed += 1 75 | if sts == 400: 76 | await db.delete_user(user['id']) 77 | done += 1 78 | if broadcast_ids.get(broadcast_id) is None: 79 | break 80 | else: 81 | broadcast_ids[broadcast_id].update( 82 | dict( 83 | current=done, 84 | failed=failed, 85 | success=success 86 | ) 87 | ) 88 | if broadcast_ids.get(broadcast_id): 89 | broadcast_ids.pop(broadcast_id) 90 | completed_in = datetime.timedelta(seconds=int(time.time() - start_time)) 91 | await asyncio.sleep(3) 92 | await out.delete() 93 | if failed == 0: 94 | await m.reply_text( 95 | text=f"broadcast completed in `{completed_in}`\n\nTotal users {total_users}.\nTotal done {done}, {success} success and {failed} failed.", 96 | quote=True 97 | ) 98 | else: 99 | await m.reply_document( 100 | document='broadcast.txt', 101 | caption=f"broadcast completed in `{completed_in}`\n\nTotal users {total_users}.\nTotal done {done}, {success} success and {failed} failed.", 102 | quote=True 103 | ) 104 | await aiofiles.os.remove('broadcast.txt') 105 | -------------------------------------------------------------------------------- /handlers/check_user_status.py: -------------------------------------------------------------------------------- 1 | # (c) Mr. Vishal & @AbirHasan2005 @PredatorHackerzZ 2 | 3 | import datetime 4 | from configs import Config 5 | from handlers.database import Database 6 | 7 | db = Database(Config.DATABASE_URL, Config.BOT_USERNAME) 8 | 9 | 10 | async def handle_user_status(bot, cmd): 11 | chat_id = cmd.from_user.id 12 | if not await db.is_user_exist(chat_id): 13 | await db.add_user(chat_id) 14 | await bot.send_message( 15 | Config.LOG_CHANNEL, 16 | f"#NEW_USER: \n\nNew User [{cmd.from_user.first_name}](tg://user?id={cmd.from_user.id}) started @{Config.BOT_USERNAME} !!" 17 | ) 18 | 19 | ban_status = await db.get_ban_status(chat_id) 20 | if ban_status["is_banned"]: 21 | if ( 22 | datetime.date.today() - datetime.date.fromisoformat(ban_status["banned_on"]) 23 | ).days > ban_status["ban_duration"]: 24 | await db.remove_ban(chat_id) 25 | else: 26 | await cmd.reply_text("You R Banned!.. Contact @TeleRoid14 😝", quote=True) 27 | return 28 | await cmd.continue_propagation() 29 | -------------------------------------------------------------------------------- /handlers/database.py: -------------------------------------------------------------------------------- 1 | # (c) @PredatorHackerzZ 2 | 3 | import datetime 4 | import motor.motor_asyncio 5 | from configs import Config 6 | 7 | 8 | class Database: 9 | 10 | def __init__(self, uri, database_name): 11 | self._client = motor.motor_asyncio.AsyncIOMotorClient(uri) 12 | self.db = self._client[database_name] 13 | self.col = self.db.users 14 | 15 | def new_user(self, id): 16 | return dict( 17 | id=id, 18 | join_date=datetime.date.today().isoformat(), 19 | ban_status=dict( 20 | is_banned=False, 21 | ban_duration=0, 22 | banned_on=datetime.date.max.isoformat(), 23 | ban_reason='' 24 | ) 25 | ) 26 | 27 | async def add_user(self, id): 28 | user = self.new_user(id) 29 | await self.col.insert_one(user) 30 | 31 | async def is_user_exist(self, id): 32 | user = await self.col.find_one({'id': int(id)}) 33 | return True if user else False 34 | 35 | async def total_users_count(self): 36 | count = await self.col.count_documents({}) 37 | return count 38 | 39 | async def get_all_users(self): 40 | all_users = self.col.find({}) 41 | return all_users 42 | 43 | async def delete_user(self, user_id): 44 | await self.col.delete_many({'id': int(user_id)}) 45 | 46 | async def remove_ban(self, id): 47 | ban_status = dict( 48 | is_banned=False, 49 | ban_duration=0, 50 | banned_on=datetime.date.max.isoformat(), 51 | ban_reason='' 52 | ) 53 | await self.col.update_one({'id': id}, {'$set': {'ban_status': ban_status}}) 54 | 55 | async def ban_user(self, user_id, ban_duration, ban_reason): 56 | ban_status = dict( 57 | is_banned=True, 58 | ban_duration=ban_duration, 59 | banned_on=datetime.date.today().isoformat(), 60 | ban_reason=ban_reason 61 | ) 62 | await self.col.update_one({'id': user_id}, {'$set': {'ban_status': ban_status}}) 63 | 64 | async def get_ban_status(self, id): 65 | default = dict( 66 | is_banned=False, 67 | ban_duration=0, 68 | banned_on=datetime.date.max.isoformat(), 69 | ban_reason='' 70 | ) 71 | user = await self.col.find_one({'id': int(id)}) 72 | return user.get('ban_status', default) 73 | 74 | async def get_all_banned_users(self): 75 | banned_users = self.col.find({'ban_status.is_banned': True}) 76 | return banned_users 77 | 78 | 79 | db = Database(Config.DATABASE_URL, Config.BOT_USERNAME) 80 | -------------------------------------------------------------------------------- /handlers/force_sub_handler.py: -------------------------------------------------------------------------------- 1 | # (c) @PredatorHackerzZ 2 | 3 | import asyncio 4 | from typing import ( 5 | Union 6 | ) 7 | from configs import Config 8 | from pyrogram import Client 9 | from pyrogram.errors import FloodWait, UserNotParticipant 10 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, Message 11 | 12 | 13 | async def get_invite_link(bot: Client, chat_id: Union[str, int]): 14 | try: 15 | invite_link = await bot.create_chat_invite_link(chat_id=chat_id) 16 | return invite_link 17 | except FloodWait as e: 18 | print(f"Sleep of {e.value}s caused by FloodWait ...") 19 | await asyncio.sleep(e.value) 20 | return await get_invite_link(bot, chat_id) 21 | 22 | 23 | async def handle_force_sub(bot: Client, cmd: Message): 24 | if Config.UPDATES_CHANNEL and Config.UPDATES_CHANNEL.startswith("-100"): 25 | channel_chat_id = int(Config.UPDATES_CHANNEL) 26 | elif Config.UPDATES_CHANNEL and (not Config.UPDATES_CHANNEL.startswith("-100")): 27 | channel_chat_id = Config.UPDATES_CHANNEL 28 | else: 29 | return 200 30 | try: 31 | user = await bot.get_chat_member(chat_id=channel_chat_id, user_id=cmd.from_user.id) 32 | if user.status == "kicked": 33 | await bot.send_message( 34 | chat_id=cmd.from_user.id, 35 | text="Sorry Sir, You are Banned to use me. Contact my [Support Group](https://t.me/TeleRoid14).", 36 | disable_web_page_preview=True 37 | ) 38 | return 400 39 | except UserNotParticipant: 40 | try: 41 | invite_link = await get_invite_link(bot, chat_id=channel_chat_id) 42 | except Exception as err: 43 | print(f"Unable to do Force Subscribe to {Config.UPDATES_CHANNEL}\n\nError: {err}") 44 | return 200 45 | await bot.send_message( 46 | chat_id=cmd.from_user.id, 47 | text="**Please Join My Updates Channel to use this Bot!**\n\n" 48 | "Due to Overload, Only Channel Subscribers can use this Bot!", 49 | reply_markup=InlineKeyboardMarkup( 50 | [ 51 | [ 52 | InlineKeyboardButton("🤖 Join Updates Channel", url=invite_link.invite_link) 53 | ], 54 | [ 55 | InlineKeyboardButton("🔄 Refresh 🔄", callback_data="refreshForceSub") 56 | ] 57 | ] 58 | ) 59 | ) 60 | return 400 61 | except Exception: 62 | await bot.send_message( 63 | chat_id=cmd.from_user.id, 64 | text="Something went Wrong. Contact my [Support Group](https://t.me/TeleRoid14).", 65 | disable_web_page_preview=True 66 | ) 67 | return 200 68 | return 200 69 | -------------------------------------------------------------------------------- /handlers/helpers.py: -------------------------------------------------------------------------------- 1 | # (c) @AbirHasan2005 2 | 3 | from base64 import standard_b64encode, standard_b64decode 4 | 5 | 6 | def str_to_b64(__str: str) -> str: 7 | str_bytes = __str.encode('ascii') 8 | bytes_b64 = standard_b64encode(str_bytes) 9 | b64 = bytes_b64.decode('ascii') 10 | return b64 11 | 12 | 13 | def b64_to_str(b64: str) -> str: 14 | bytes_b64 = b64.encode('ascii') 15 | bytes_str = standard_b64decode(bytes_b64) 16 | __str = bytes_str.decode('ascii') 17 | return __str 18 | -------------------------------------------------------------------------------- /handlers/save_media.py: -------------------------------------------------------------------------------- 1 | # (c) @AbirHasan2005 | @PredatorHackerzZ | @MrAbhi2k3 2 | 3 | import asyncio 4 | import requests 5 | import string 6 | import random 7 | from configs import Config 8 | from pyrogram import Client 9 | from pyrogram.types import ( 10 | Message, 11 | InlineKeyboardMarkup, 12 | InlineKeyboardButton 13 | ) 14 | from pyrogram.errors import FloodWait 15 | from handlers.helpers import str_to_b64 16 | 17 | def generate_random_alphanumeric(): 18 | """Generate a random 8-letter alphanumeric string.""" 19 | characters = string.ascii_letters + string.digits 20 | random_chars = ''.join(random.choice(characters) for _ in range(8)) 21 | return random_chars 22 | 23 | def get_short(url): 24 | rget = requests.get(f"https://{Config.SHORTLINK_URL}/api?api={Config.SHORTLINK_API}&url={url}&alias={generate_random_alphanumeric()}") 25 | rjson = rget.json() 26 | if rjson["status"] == "success" or rget.status_code == 200: 27 | return rjson["shortenedUrl"] 28 | else: 29 | return url 30 | 31 | 32 | async def forward_to_channel(bot: Client, message: Message, editable: Message): 33 | try: 34 | __SENT = await message.forward(Config.DB_CHANNEL) 35 | return __SENT 36 | except FloodWait as sl: 37 | if sl.value > 45: 38 | await asyncio.sleep(sl.value) 39 | await bot.send_message( 40 | chat_id=int(Config.LOG_CHANNEL), 41 | text=f"#FloodWait:\nGot FloodWait of `{str(sl.value)}s` from `{str(editable.chat.id)}` !!", 42 | disable_web_page_preview=True, 43 | reply_markup=InlineKeyboardMarkup( 44 | [ 45 | [InlineKeyboardButton("Ban User", callback_data=f"ban_user_{str(editable.chat.id)}")] 46 | ] 47 | ) 48 | ) 49 | return await forward_to_channel(bot, message, editable) 50 | 51 | async def save_batch_media_in_channel(bot: Client, editable: Message, message_ids: list): 52 | try: 53 | if editable.reply_to_message.from_user.id not in Config.OTHER_USERS_CAN_SAVE_FILE: 54 | await editable.reply_text("You are not authorized to save files.") 55 | return 56 | 57 | message_ids_str = "" 58 | for message_id in message_ids: 59 | message = await bot.get_messages(chat_id=editable.chat.id, message_ids=message_id) 60 | sent_message = await forward_to_channel(bot, message, editable) 61 | if sent_message is None: 62 | continue 63 | message_ids_str += f"{str(sent_message.id)} " 64 | await asyncio.sleep(2) 65 | SaveMessage = await bot.send_message( 66 | chat_id=Config.DB_CHANNEL, 67 | text=message_ids_str, 68 | disable_web_page_preview=True, 69 | reply_markup=InlineKeyboardMarkup([[ 70 | InlineKeyboardButton("Delete Batch", callback_data="closeMessage") 71 | ]]) 72 | ) 73 | share_link = f"https://telegram.me/{Config.BOT_USERNAME}?start=PredatorHackerzZ_{str_to_b64(str(SaveMessage.id))}" 74 | short_link = get_short(share_link) 75 | await editable.edit( 76 | f"**Batch Files Stored in my Database!**\n\nHere is the Permanent Link of your files: {short_link} \n\n" 77 | f"Just Click the link to get your files!", 78 | reply_markup=InlineKeyboardMarkup( 79 | [[InlineKeyboardButton("Original Link", url=share_link), 80 | InlineKeyboardButton("Short Link", url=short_link)], 81 | [InlineKeyboardButton("Bots Channel", url="https://t.me/TeleRoidGroup"), 82 | InlineKeyboardButton("Support Group", url="https://t.me/TeleRoid14")]] 83 | ), 84 | disable_web_page_preview=True 85 | ) 86 | await bot.send_message( 87 | chat_id=int(Config.LOG_CHANNEL), 88 | text=f"#BATCH_SAVE:\n\n[{editable.reply_to_message.from_user.first_name}](tg://user?id={editable.reply_to_message.from_user.id}) Got Batch Link!", 89 | disable_web_page_preview=True, 90 | reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("Original Link", url=short_link), 91 | InlineKeyboardButton("Short Link", url=share_link)]]) 92 | ) 93 | except Exception as err: 94 | await editable.edit(f"Something Went Wrong!\n\n**Error:** `{err}`") 95 | await bot.send_message( 96 | chat_id=int(Config.LOG_CHANNEL), 97 | text=f"#ERROR_TRACEBACK:\nGot Error from `{str(editable.chat.id)}` !!\n\n**Traceback:** `{err}`", 98 | disable_web_page_preview=True, 99 | reply_markup=InlineKeyboardMarkup( 100 | [ 101 | [InlineKeyboardButton("Ban User", callback_data=f"ban_user_{str(editable.chat.id)}")] 102 | ] 103 | ) 104 | ) 105 | 106 | 107 | async def save_media_in_channel(bot: Client, editable: Message, message: Message): 108 | try: 109 | if message.from_user.id not in Config.OTHER_USERS_CAN_SAVE_FILE: 110 | await editable.reply_text("You are not authorized to save files.") 111 | return 112 | forwarded_msg = await message.forward(Config.DB_CHANNEL) 113 | file_er_id = str(forwarded_msg.id) 114 | await forwarded_msg.reply_text( 115 | f"#PRIVATE_FILE:\n\n[{message.from_user.first_name}](tg://user?id={message.from_user.id}) Got File Link!", 116 | disable_web_page_preview=True) 117 | share_link = f"https://telegram.me/{Config.BOT_USERNAME}?start=PredatorHackerzZ_{str_to_b64(file_er_id)}" 118 | short_link = get_short(share_link) 119 | await editable.edit( 120 | "**Your File Stored in my Database!**\n\n" 121 | f"Here is the Permanent Link of your file: {short_link} \n\n" 122 | "Just Click the link to get your file!", 123 | reply_markup=InlineKeyboardMarkup( 124 | [[InlineKeyboardButton("Original Link", url=share_link), 125 | InlineKeyboardButton("Short Link", url=short_link)], 126 | [InlineKeyboardButton("Bots Channel", url="https://t.me/TeleRoidGroup"), 127 | InlineKeyboardButton("Support Group", url="https://t.me/TeleRoid14")]] 128 | ), 129 | disable_web_page_preview=True 130 | ) 131 | except FloodWait as sl: 132 | if sl.value > 45: 133 | print(f"Sleep of {sl.value}s caused by FloodWait ...") 134 | await asyncio.sleep(sl.value) 135 | await bot.send_message( 136 | chat_id=int(Config.LOG_CHANNEL), 137 | text="#FloodWait:\n" 138 | f"Got FloodWait of `{str(sl.value)}s` from `{str(editable.chat.id)}` !!", 139 | disable_web_page_preview=True, 140 | reply_markup=InlineKeyboardMarkup( 141 | [ 142 | [InlineKeyboardButton("Ban User", callback_data=f"ban_user_{str(editable.chat.id)}")] 143 | ] 144 | ) 145 | ) 146 | await save_media_in_channel(bot, editable, message) 147 | except Exception as err: 148 | await editable.edit(f"Something Went Wrong!\n\n**Error:** `{err}`") 149 | await bot.send_message( 150 | chat_id=int(Config.LOG_CHANNEL), 151 | text="#ERROR_TRACEBACK:\n" 152 | f"Got Error from `{str(editable.chat.id)}` !!\n\n" 153 | f"**Traceback:** `{err}`", 154 | disable_web_page_preview=True, 155 | reply_markup=InlineKeyboardMarkup( 156 | [ 157 | [InlineKeyboardButton("Ban User", callback_data=f"ban_user_{str(editable.chat.id)}")] 158 | ] 159 | ) 160 | ) 161 | -------------------------------------------------------------------------------- /handlers/send_file.py: -------------------------------------------------------------------------------- 1 | # Updated By @MrAbhi2k3 2 | 3 | import asyncio 4 | import requests 5 | import string 6 | import random 7 | from configs import Config 8 | from pyrogram import Client 9 | from pyrogram.types import Message 10 | from pyrogram.errors import FloodWait 11 | from handlers.helpers import str_to_b64 12 | 13 | async def reply_forward(message: Message, file_id: int): 14 | try: 15 | await message.reply_text( 16 | f"Files will be deleted in 30 minutes to avoid copyright issues. Please forward and save them.", 17 | disable_web_page_preview=True, 18 | quote=True 19 | ) 20 | except FloodWait as e: 21 | await asyncio.sleep(e.x) 22 | await reply_forward(message, file_id) 23 | 24 | async def media_forward(bot: Client, user_id: int, file_id: int): 25 | try: 26 | if Config.FORWARD_AS_COPY is True: 27 | return await bot.copy_message(chat_id=user_id, from_chat_id=Config.DB_CHANNEL, 28 | message_id=file_id) 29 | elif Config.FORWARD_AS_COPY is False: 30 | return await bot.forward_messages(chat_id=user_id, from_chat_id=Config.DB_CHANNEL, 31 | message_ids=file_id) 32 | except FloodWait as e: 33 | await asyncio.sleep(e.value) 34 | return media_forward(bot, user_id, file_id) 35 | await message.delete() 36 | 37 | async def send_media_and_reply(bot: Client, user_id: int, file_id: int): 38 | sent_message = await media_forward(bot, user_id, file_id) 39 | await reply_forward(message=sent_message, file_id=file_id) 40 | asyncio.create_task(delete_after_delay(sent_message, 1800)) 41 | 42 | async def delete_after_delay(message, delay): 43 | await asyncio.sleep(delay) 44 | await message.delete() 45 | -------------------------------------------------------------------------------- /heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | worker: Dockerfile 4 | -------------------------------------------------------------------------------- /render.yaml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | worker: Dockerfile 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Pyrogram 2 | TgCrypto 3 | motor 4 | aiofiles 5 | dnspython 6 | psutil 7 | render 8 | requests 9 | --------------------------------------------------------------------------------