├── .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 | 
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 |  🤖
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 | [](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 |
--------------------------------------------------------------------------------