├── Dockerfile
├── LICENSE
├── Procfile
├── README.md
├── Script.py
├── TechVJ
├── __init__.py
├── bot
│ ├── TechVJ
│ ├── __init__.py
│ └── clients.py
├── server
│ ├── TechVJ
│ ├── __init__.py
│ ├── exceptions.py
│ └── stream_routes.py
├── template
│ ├── TechVJ
│ ├── dl.html
│ └── req.html
└── utils
│ ├── TechVJ
│ ├── config_parser.py
│ ├── custom_dl.py
│ ├── file_properties.py
│ ├── file_size.py
│ ├── human_readable.py
│ ├── keepalive.py
│ ├── render_template.py
│ └── time_format.py
├── app.py
├── bot.py
├── clone_plugins
├── TechVJ
├── broadcast.py
├── commands.py
├── dbusers.py
├── genlink.py
└── users_api.py
├── config.py
├── logging.conf
├── plugins
├── TechVJ
├── broadcast.py
├── clone.py
├── commands.py
├── dbusers.py
├── genlink.py
└── users_api.py
├── requirements.txt
├── run cmd.txt
├── runtime.txt
└── utils.py
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Don't Remove Credit @VJ_Botz
2 | # Subscribe YouTube Channel For Amazing Bot @Tech_VJ
3 | # Ask Doubt on telegram @KingVJ01
4 |
5 | FROM python:3.10.8-slim-buster
6 |
7 | RUN apt update && apt upgrade -y
8 | RUN apt install git -y
9 | COPY requirements.txt /requirements.txt
10 |
11 | RUN cd /
12 | RUN pip3 install -U pip && pip3 install -U -r requirements.txt
13 | RUN mkdir /VJ-File-Store
14 | WORKDIR /VJ-File-Store
15 | COPY . /VJ-File-Store
16 | CMD ["python", "bot.py"]
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
2 |
3 |
5 | VJ FILE STORE BOT
6 |
7 |
8 | 
9 |
/newbot
ᴛᴏ @BotFather
81 | 2) ɢɪᴠᴇ ᴀ ɴᴀᴍᴇ ꜰᴏʀ ʏᴏᴜʀ ʙᴏᴛ.
82 | 3) ɢɪᴠᴇ ᴀ ᴜɴɪǫᴜᴇ ᴜsᴇʀɴᴀᴍᴇ.
83 | 4) ᴛʜᴇɴ ʏᴏᴜ ᴡɪʟʟ ɢᴇᴛ ᴀ ᴍᴇssᴀɢᴇ ᴡɪᴛʜ ʏᴏᴜʀ ʙᴏᴛ ᴛᴏᴋᴇɴ.
84 | 5) ꜰᴏʀᴡᴀʀᴅ ᴛʜᴀᴛ ᴍᴇssᴀɢᴇ ᴛᴏ ᴍᴇ.
85 |
86 | ᴛʜᴇɴ ɪ ᴀᴍ ᴛʀʏ ᴛᴏ ᴄʀᴇᴀᴛᴇ ᴀ ᴄᴏᴘʏ ʙᴏᴛ ᴏғ ᴍᴇ ғᴏʀ ʏᴏᴜ ᴏɴʟʏ 😌"""
87 |
88 | # Don't Remove Credit Tg - @VJ_Botz
89 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
90 | # Ask Doubt on telegram @KingVJ01
91 |
92 | HELP_TXT = """💢 HOW TO USE THE BOT ☺️
93 |
94 | 🔻 /link - ʀᴇᴘʟʏ ᴛᴏ ᴀ ᴠɪᴅᴇᴏ ᴏʀ ғɪʟᴇ ᴛᴏ ɢᴇᴛ sʜᴀʀᴀʙʟᴇ ʟɪɴᴋ
95 |
96 | 🔻 /batch - sᴇɴᴅ ғɪʀsᴛ ʟɪɴᴋ ᴏғ ғɪʟᴇ sᴛᴏʀᴇ ᴄʜᴀɴɴᴇʟ ᴘᴏsᴛ ᴛʜᴇɴ ʟᴀsᴛ ᴘᴏsᴛ ʟɪɴᴋ ᴀɴᴅ ᴍᴀᴋᴇ sᴜʀᴇ ʙᴏᴛ ɪs ᴀᴅᴍɪɴ ɪɴ ʏᴏᴜʀ ғɪʟᴇ sᴛᴏʀᴇ ᴄʜᴀɴɴᴇʟ.
97 | ᴇx - /batch https://t.me/vj_botz/25 https://t.me/vj_botz/30
98 |
99 | 🔻 /clone - ᴄʀᴇᴀᴛᴇ ʏᴏᴜʀ ᴏᴡɴ ɪᴅᴇɴᴛɪᴄᴀʟ ᴄʟᴏɴᴇ ʙᴏᴛ
100 |
101 | 🔻 /base_site - ᴜsᴇ ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ᴛᴏ sᴇᴛ ᴜʀʟ sʜᴏʀᴛɴᴇʀ ʟɪɴᴋ ᴅᴏᴍᴀɪɴ
102 | ᴇx - /base_site ʏᴏᴜʀᴅᴏᴍᴀɪɴ.ᴄᴏᴍ
103 |
104 | 🔻 /api - sᴇᴛ ʏᴏᴜʀ ᴜʀʟ sʜᴏʀᴛɴᴇʀ ᴀᴄᴄᴏᴜɴᴛ ᴀᴘɪ
105 | ᴇx - /api ʙᴀᴏᴡɢᴡᴋʟᴀᴀʙᴀᴋʟ
106 |
107 | 🔻 /deletecloned - ᴜsᴇ ᴛʜɪs ғᴏʀ ᴅᴇʟᴇᴛᴇ ʏᴏᴜʀ ᴄʟᴏɴᴇ ʙᴏᴛ
108 |
109 | 🔻 /broadcast - ʀᴇᴘʟʏ ᴛᴏ ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ᴛᴏ ᴀ ᴍᴇssᴀɢᴇ ᴛᴏ ʙʀᴏᴀᴅᴄᴀsᴛ (ʙᴏᴛ ᴏᴡɴᴇʀ ᴏɴʟʏ)"""
110 |
111 | # Don't Remove Credit Tg - @VJ_Botz
112 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
113 | # Ask Doubt on telegram @KingVJ01
114 |
115 |
116 | CHELP_TXT = """💢 Hᴏᴡ Tᴏ Usᴇ Tʜɪs Bᴏᴛ ☺️
117 |
118 | 🔻 /link - ʀᴇᴘʟʏ ᴛᴏ ᴀ ᴠɪᴅᴇᴏ ᴏʀ ғɪʟᴇ ᴛᴏ ɢᴇᴛ sʜᴀʀᴀʙʟᴇ ʟɪɴᴋ
119 |
120 | 🔻 /base_site - ᴜsᴇ ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ᴛᴏ sᴇᴛ ᴜʀʟ sʜᴏʀᴛɴᴇʀ ʟɪɴᴋ ᴅᴏᴍᴀɪɴ
121 | ᴇx - /base_site ʏᴏᴜʀᴅᴏᴍᴀɪɴ.ᴄᴏᴍ
122 |
123 | 🔻 /api - sᴇᴛ ʏᴏᴜʀ ᴜʀʟ sʜᴏʀᴛɴᴇʀ ᴀᴄᴄᴏᴜɴᴛ ᴀᴘɪ
124 | ᴇx - /api ʙᴀᴏᴡɢᴡᴋʟᴀᴀʙᴀᴋʟ
125 |
126 | 🔻 /broadcast - ʀᴇᴘʟʏ ᴛᴏ ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ᴛᴏ ᴀ ᴍᴇssᴀɢᴇ ᴛᴏ ʙʀᴏᴀᴅᴄᴀsᴛ (ʙᴏᴛ ᴏᴡɴᴇʀ ᴏɴʟʏ)"""
127 |
128 | # Don't Remove Credit Tg - @VJ_Botz
129 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
130 | # Ask Doubt on telegram @KingVJ01
131 |
132 | LOG_TEXT = """#NewUser
133 |
134 | ID - {}
135 |
136 | Nᴀᴍᴇ - {}
137 | """
138 | RESTART_TXT = """
139 | Bᴏᴛ Rᴇsᴛᴀʀᴛᴇᴅ !
140 |
141 | 📅 Dᴀᴛᴇ : {}
142 | ⏰ Tɪᴍᴇ : {}
143 | 🌐 Tɪᴍᴇᴢᴏɴᴇ : Asia/Kolkata
144 | 🛠️ Bᴜɪʟᴅ Sᴛᴀᴛᴜs: v2.7.1 [ Sᴛᴀʙʟᴇ ]
"""
145 |
146 | # Don't Remove Credit Tg - @VJ_Botz
147 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
148 | # Ask Doubt on telegram @KingVJ01
149 |
--------------------------------------------------------------------------------
/TechVJ/__init__.py:
--------------------------------------------------------------------------------
1 | import time
2 | StartTime = time.time()
3 | __version__ = 1.1
4 |
--------------------------------------------------------------------------------
/TechVJ/bot/TechVJ:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/TechVJ/bot/__init__.py:
--------------------------------------------------------------------------------
1 | from pyrogram import Client, types
2 | from config import *
3 | from typing import Union, Optional, AsyncGenerator
4 | from aiohttp import web
5 |
6 | class StreamXBot(Client):
7 |
8 | def __init__(self):
9 | super().__init__(
10 | name="vjfiletolink",
11 | api_id=API_ID,
12 | api_hash=API_HASH,
13 | bot_token=BOT_TOKEN,
14 | workers=50,
15 | plugins={"root": "plugins"},
16 | sleep_threshold=5,
17 | )
18 | async def iter_messages(
19 | self,
20 | chat_id: Union[int, str],
21 | limit: int,
22 | offset: int = 0,
23 | ) -> Optional[AsyncGenerator["types.Message", None]]:
24 | """Iterate through a chat sequentially.
25 | This convenience method does the same as repeatedly calling :meth:`~pyrogram.Client.get_messages` in a loop, thus saving
26 | you from the hassle of setting up boilerplate code. It is useful for getting the whole chat messages with a
27 | single call.
28 | Parameters:
29 | chat_id (``int`` | ``str``):
30 | Unique identifier (int) or username (str) of the target chat.
31 | For your personal cloud (Saved Messages) you can simply use "me" or "self".
32 | For a contact that exists in your Telegram address book you can use his phone number (str).
33 |
34 | limit (``int``):
35 | Identifier of the last message to be returned.
36 |
37 | offset (``int``, *optional*):
38 | Identifier of the first message to be returned.
39 | Defaults to 0.
40 | Returns:
41 | ``Generator``: A generator yielding :obj:`~pyrogram.types.Message` objects.
42 | Example:
43 | .. code-block:: python
44 | for message in app.iter_messages("pyrogram", 1, 15000):
45 | print(message.text)
46 | """
47 | current = offset
48 | while True:
49 | new_diff = min(200, limit - current)
50 | if new_diff <= 0:
51 | return
52 | messages = await self.get_messages(chat_id, list(range(current, current+new_diff+1)))
53 | for message in messages:
54 | yield message
55 | current += 1
56 |
57 | StreamBot = StreamXBot()
58 |
59 | multi_clients = {}
60 | work_loads = {}
61 |
--------------------------------------------------------------------------------
/TechVJ/bot/clients.py:
--------------------------------------------------------------------------------
1 | # (c) adarsh-goel
2 |
3 | import asyncio
4 | import logging
5 | from config import API_HASH, API_ID, MULTI_CLIENT, SLEEP_THRESHOLD
6 | from pyrogram import Client
7 | from TechVJ.utils.config_parser import TokenParser
8 | from . import multi_clients, work_loads, StreamBot
9 |
10 |
11 | async def initialize_clients():
12 | multi_clients[0] = StreamBot
13 | work_loads[0] = 0
14 | all_tokens = TokenParser().parse_from_env()
15 | if not all_tokens:
16 | print("No additional clients found, using default client")
17 | return
18 |
19 | async def start_client(client_id, token):
20 | try:
21 | print(f"Starting - Client {client_id}")
22 | if client_id == len(all_tokens):
23 | await asyncio.sleep(2)
24 | print("This will take some time, please wait...")
25 | client = await Client(
26 | name=str(client_id),
27 | api_id=API_ID,
28 | api_hash=API_HASH,
29 | bot_token=token,
30 | sleep_threshold=SLEEP_THRESHOLD,
31 | no_updates=True,
32 | in_memory=True
33 | ).start()
34 | work_loads[client_id] = 0
35 | return client_id, client
36 | except Exception:
37 | logging.error(f"Failed starting Client - {client_id} Error:", exc_info=True)
38 |
39 | clients = await asyncio.gather(*[start_client(i, token) for i, token in all_tokens.items()])
40 | multi_clients.update(dict(clients))
41 | if len(multi_clients) != 1:
42 | MULTI_CLIENT = True
43 | print("Multi-Client Mode Enabled")
44 | else:
45 | print("No additional clients were initialized, using default client")
46 |
--------------------------------------------------------------------------------
/TechVJ/server/TechVJ:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/TechVJ/server/__init__.py:
--------------------------------------------------------------------------------
1 | from aiohttp import web
2 | from .stream_routes import routes
3 |
4 |
5 | async def web_server():
6 | web_app = web.Application(client_max_size=30000000)
7 | web_app.add_routes(routes)
8 | return web_app
9 |
--------------------------------------------------------------------------------
/TechVJ/server/exceptions.py:
--------------------------------------------------------------------------------
1 |
2 | class InvalidHash(Exception):
3 | message = "Invalid hash"
4 |
5 | class FIleNotFound(Exception):
6 | message = "File not found"
--------------------------------------------------------------------------------
/TechVJ/server/stream_routes.py:
--------------------------------------------------------------------------------
1 | import re
2 | import time
3 | import math
4 | import logging
5 | import secrets
6 | import mimetypes
7 | from aiohttp import web
8 | from aiohttp.http_exceptions import BadStatusLine
9 | from TechVJ.bot import multi_clients, work_loads, StreamBot
10 | from TechVJ.server.exceptions import FIleNotFound, InvalidHash
11 | from TechVJ import StartTime, __version__
12 | from ..utils.time_format import get_readable_time
13 | from ..utils.custom_dl import ByteStreamer
14 | from TechVJ.utils.render_template import render_page
15 | from config import MULTI_CLIENT
16 |
17 |
18 | routes = web.RouteTableDef()
19 |
20 | @routes.get("/", allow_head=True)
21 | async def root_route_handler(_):
22 | return web.json_response(
23 | {
24 | "server_status": "running",
25 | "uptime": get_readable_time(time.time() - StartTime),
26 | "telegram_bot": "@" + StreamBot.username,
27 | "connected_bots": len(multi_clients),
28 | "loads": dict(
29 | ("bot" + str(c + 1), l)
30 | for c, (_, l) in enumerate(
31 | sorted(work_loads.items(), key=lambda x: x[1], reverse=True)
32 | )
33 | ),
34 | "version": __version__,
35 | }
36 | )
37 |
38 |
39 | @routes.get(r"/watch/{path:\S+}", allow_head=True)
40 | async def stream_handler(request: web.Request):
41 | try:
42 | path = request.match_info["path"]
43 | match = re.search(r"^([a-zA-Z0-9_-]{6})(\d+)$", path)
44 | if match:
45 | secure_hash = match.group(1)
46 | id = int(match.group(2))
47 | else:
48 | id = int(re.search(r"(\d+)(?:\/\S+)?", path).group(1))
49 | secure_hash = request.rel_url.query.get("hash")
50 | return web.Response(text=await render_page(id, secure_hash), content_type='text/html')
51 | except InvalidHash as e:
52 | raise web.HTTPForbidden(text=e.message)
53 | except FIleNotFound as e:
54 | raise web.HTTPNotFound(text=e.message)
55 | except (AttributeError, BadStatusLine, ConnectionResetError):
56 | pass
57 | except Exception as e:
58 | logging.critical(e.with_traceback(None))
59 | raise web.HTTPInternalServerError(text=str(e))
60 |
61 | @routes.get(r"/{path:\S+}", allow_head=True)
62 | async def stream_handler(request: web.Request):
63 | try:
64 | path = request.match_info["path"]
65 | match = re.search(r"^([a-zA-Z0-9_-]{6})(\d+)$", path)
66 | if match:
67 | secure_hash = match.group(1)
68 | id = int(match.group(2))
69 | else:
70 | id = int(re.search(r"(\d+)(?:\/\S+)?", path).group(1))
71 | secure_hash = request.rel_url.query.get("hash")
72 | return await media_streamer(request, id, secure_hash)
73 | except InvalidHash as e:
74 | raise web.HTTPForbidden(text=e.message)
75 | except FIleNotFound as e:
76 | raise web.HTTPNotFound(text=e.message)
77 | except (AttributeError, BadStatusLine, ConnectionResetError):
78 | pass
79 | except Exception as e:
80 | logging.critical(e.with_traceback(None))
81 | raise web.HTTPInternalServerError(text=str(e))
82 |
83 | class_cache = {}
84 |
85 | async def media_streamer(request: web.Request, id: int, secure_hash: str):
86 | range_header = request.headers.get("Range", 0)
87 |
88 | index = min(work_loads, key=work_loads.get)
89 | faster_client = multi_clients[index]
90 |
91 | if MULTI_CLIENT:
92 | logging.info(f"Client {index} is now serving {request.remote}")
93 |
94 | if faster_client in class_cache:
95 | tg_connect = class_cache[faster_client]
96 | logging.debug(f"Using cached ByteStreamer object for client {index}")
97 | else:
98 | logging.debug(f"Creating new ByteStreamer object for client {index}")
99 | tg_connect = ByteStreamer(faster_client)
100 | class_cache[faster_client] = tg_connect
101 | logging.debug("before calling get_file_properties")
102 | file_id = await tg_connect.get_file_properties(id)
103 | logging.debug("after calling get_file_properties")
104 |
105 | if file_id.unique_id[:6] != secure_hash:
106 | logging.debug(f"Invalid hash for message with ID {id}")
107 | raise InvalidHash
108 |
109 | file_size = file_id.file_size
110 |
111 | if range_header:
112 | from_bytes, until_bytes = range_header.replace("bytes=", "").split("-")
113 | from_bytes = int(from_bytes)
114 | until_bytes = int(until_bytes) if until_bytes else file_size - 1
115 | else:
116 | from_bytes = request.http_range.start or 0
117 | until_bytes = (request.http_range.stop or file_size) - 1
118 |
119 | if (until_bytes > file_size) or (from_bytes < 0) or (until_bytes < from_bytes):
120 | return web.Response(
121 | status=416,
122 | body="416: Range not satisfiable",
123 | headers={"Content-Range": f"bytes */{file_size}"},
124 | )
125 |
126 | chunk_size = 1024 * 1024
127 | until_bytes = min(until_bytes, file_size - 1)
128 |
129 | offset = from_bytes - (from_bytes % chunk_size)
130 | first_part_cut = from_bytes - offset
131 | last_part_cut = until_bytes % chunk_size + 1
132 |
133 | req_length = until_bytes - from_bytes + 1
134 | part_count = math.ceil(until_bytes / chunk_size) - math.floor(offset / chunk_size)
135 | body = tg_connect.yield_file(
136 | file_id, index, offset, first_part_cut, last_part_cut, part_count, chunk_size
137 | )
138 |
139 | mime_type = file_id.mime_type
140 | file_name = file_id.file_name
141 | disposition = "attachment"
142 |
143 | if mime_type:
144 | if not file_name:
145 | try:
146 | file_name = f"{secrets.token_hex(2)}.{mime_type.split('/')[1]}"
147 | except (IndexError, AttributeError):
148 | file_name = f"{secrets.token_hex(2)}.unknown"
149 | else:
150 | if file_name:
151 | mime_type = mimetypes.guess_type(file_id.file_name)
152 | else:
153 | mime_type = "application/octet-stream"
154 | file_name = f"{secrets.token_hex(2)}.unknown"
155 |
156 | return web.Response(
157 | status=206 if range_header else 200,
158 | body=body,
159 | headers={
160 | "Content-Type": f"{mime_type}",
161 | "Content-Range": f"bytes {from_bytes}-{until_bytes}/{file_size}",
162 | "Content-Length": str(req_length),
163 | "Content-Disposition": f'{disposition}; filename="{file_name}"',
164 | "Accept-Ranges": "bytes",
165 | },
166 | )
167 |
--------------------------------------------------------------------------------
/TechVJ/template/TechVJ:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/TechVJ/template/dl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 140 | 141 | %s 142 | 143 |
144 |141 | 142 | {{file_name}} 143 | 144 |
145 |Play with...
162 |{title}
"
89 | if CUSTOM_FILE_CAPTION:
90 | try:
91 | f_caption=CUSTOM_FILE_CAPTION.format(file_name= '' if title is None else title, file_size='' if size is None else size, file_caption='')
92 | except:
93 | return
94 | await msg.edit_caption(f_caption)
95 | k = await msg.reply(f"❗️❗️❗️IMPORTANT❗️️❗️❗️\n\nThis Movie File/Video will be deleted in {AUTO_DELETE} mins 🫥 (Due to Copyright Issues).\n\nPlease forward this File/Video to your Saved Messages and Start Download there",quote=True)
96 | await asyncio.sleep(AUTO_DELETE_TIME)
97 | await msg.delete()
98 | await k.edit_text("Your File/Video is successfully deleted!!!")
99 | return
100 | except:
101 | pass
102 |
103 | # Don't Remove Credit Tg - @VJ_Botz
104 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
105 | # Ask Doubt on telegram @KingVJ01
106 |
107 | @Client.on_message(filters.command('api') & filters.private)
108 | async def shortener_api_handler(client, m: Message):
109 | user_id = m.from_user.id
110 | user = await get_user(user_id)
111 | cmd = m.command
112 |
113 | if len(cmd) == 1:
114 | s = script.SHORTENER_API_MESSAGE.format(base_site=user["base_site"], shortener_api=user["shortener_api"])
115 | return await m.reply(s)
116 |
117 | elif len(cmd) == 2:
118 | api = cmd[1].strip()
119 | await update_user_info(user_id, {"shortener_api": api})
120 | await m.reply("Shortener API updated successfully to " + api)
121 | else:
122 | await m.reply("You are not authorized to use this command.")
123 |
124 | # Don't Remove Credit Tg - @VJ_Botz
125 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
126 | # Ask Doubt on telegram @KingVJ01
127 |
128 | @Client.on_message(filters.command("base_site") & filters.private)
129 | async def base_site_handler(client, m: Message):
130 | user_id = m.from_user.id
131 | user = await get_user(user_id)
132 | cmd = m.command
133 | text = f"/base_site (base_site)\n\nCurrent base site: None\n\n EX: /base_site shortnerdomain.com\n\nIf You Want To Remove Base Site Then Copy This And Send To Bot - `/base_site None`"
134 |
135 | if len(cmd) == 1:
136 | return await m.reply(text=text, disable_web_page_preview=True)
137 | elif len(cmd) == 2:
138 | base_site = cmd[1].strip()
139 | if not domain(base_site):
140 | return await m.reply(text=text, disable_web_page_preview=True)
141 | await update_user_info(user_id, {"base_site": base_site})
142 | await m.reply("Base Site updated successfully")
143 | else:
144 | await m.reply("You are not authorized to use this command.")
145 |
146 | # Don't Remove Credit Tg - @VJ_Botz
147 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
148 | # Ask Doubt on telegram @KingVJ01
149 |
150 |
151 | @Client.on_callback_query()
152 | async def cb_handler(client: Client, query: CallbackQuery):
153 | me = await client.get_me()
154 | if query.data == "close_data":
155 | await query.message.delete()
156 | elif query.data == "start":
157 | buttons = [[
158 | InlineKeyboardButton('💝 sᴜʙsᴄʀɪʙᴇ ᴍʏ ʏᴏᴜᴛᴜʙᴇ ᴄʜᴀɴɴᴇʟ', url='https://youtube.com/@Tech_VJ')
159 | ],[
160 | InlineKeyboardButton('🤖 ᴄʀᴇᴀᴛᴇ ʏᴏᴜʀ ᴏᴡɴ ᴄʟᴏɴᴇ ʙᴏᴛ', url=f'https://t.me/{BOT_USERNAME}?start=clone')
161 | ],[
162 | InlineKeyboardButton('💁♀️ ʜᴇʟᴘ', callback_data='help'),
163 | InlineKeyboardButton('ᴀʙᴏᴜᴛ 🔻', callback_data='about')
164 | ]]
165 |
166 | reply_markup = InlineKeyboardMarkup(buttons)
167 | await client.edit_message_media(
168 | query.message.chat.id,
169 | query.message.id,
170 | InputMediaPhoto(random.choice(PICS))
171 | )
172 | await query.message.edit_text(
173 | text=script.CLONE_START_TXT.format(query.from_user.mention, me.mention),
174 | reply_markup=reply_markup,
175 | parse_mode=enums.ParseMode.HTML
176 | )
177 |
178 | # Don't Remove Credit Tg - @VJ_Botz
179 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
180 | # Ask Doubt on telegram @KingVJ01
181 |
182 | elif query.data == "help":
183 | buttons = [[
184 | InlineKeyboardButton('Hᴏᴍᴇ', callback_data='start'),
185 | InlineKeyboardButton('🔒 Cʟᴏsᴇ', callback_data='close_data')
186 | ]]
187 | await client.edit_message_media(
188 | query.message.chat.id,
189 | query.message.id,
190 | InputMediaPhoto(random.choice(PICS))
191 | )
192 | reply_markup = InlineKeyboardMarkup(buttons)
193 | await query.message.edit_text(
194 | text=script.CHELP_TXT,
195 | reply_markup=reply_markup,
196 | parse_mode=enums.ParseMode.HTML
197 | )
198 |
199 | elif query.data == "about":
200 | buttons = [[
201 | InlineKeyboardButton('Hᴏᴍᴇ', callback_data='start'),
202 | InlineKeyboardButton('🔒 Cʟᴏsᴇ', callback_data='close_data')
203 | ]]
204 | await client.edit_message_media(
205 | query.message.chat.id,
206 | query.message.id,
207 | InputMediaPhoto(random.choice(PICS))
208 | )
209 | owner = mongo_db.bots.find_one({'bot_id': me.id})
210 | ownerid = int(owner['user_id'])
211 | reply_markup = InlineKeyboardMarkup(buttons)
212 | await query.message.edit_text(
213 | text=script.CABOUT_TXT.format(me.mention, ownerid),
214 | reply_markup=reply_markup,
215 | parse_mode=enums.ParseMode.HTML
216 | )
217 |
218 | # Don't Remove Credit Tg - @VJ_Botz
219 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
220 | # Ask Doubt on telegram @KingVJ01
221 |
--------------------------------------------------------------------------------
/clone_plugins/dbusers.py:
--------------------------------------------------------------------------------
1 | import motor.motor_asyncio
2 | from config import CDB_NAME, CLONE_DB_URI
3 |
4 | class Database:
5 |
6 | def __init__(self, uri, database_name):
7 | self._client = motor.motor_asyncio.AsyncIOMotorClient(uri)
8 | self.db = self._client[database_name]
9 |
10 | async def add_user(self, bot_id, user_id):
11 | user = {'user_id': int(user_id)}
12 | await self.db[str(bot_id)].insert_one(user)
13 |
14 | async def is_user_exist(self, bot_id, id):
15 | user = await self.db[str(bot_id)].find_one({'user_id': int(id)})
16 | return bool(user)
17 |
18 | async def total_users_count(self, bot_id):
19 | count = await self.db[str(bot_id)].count_documents({})
20 | return count
21 |
22 | async def get_all_users(self, bot_id):
23 | return self.db[str(bot_id)].find({})
24 |
25 | async def delete_user(self, bot_id, user_id):
26 | await self.db[str(bot_id)].delete_many({'user_id': int(user_id)})
27 |
28 |
29 | clonedb = Database(CLONE_DB_URI, CDB_NAME)
30 |
--------------------------------------------------------------------------------
/clone_plugins/genlink.py:
--------------------------------------------------------------------------------
1 | # Don't Remove Credit @VJ_Botz
2 | # Subscribe YouTube Channel For Amazing Bot @Tech_VJ
3 | # Ask Doubt on telegram @KingVJ01
4 |
5 | import re
6 | from pyrogram import filters, Client, enums
7 | from clone_plugins.users_api import get_user, get_short_link
8 | import base64
9 |
10 | # Don't Remove Credit Tg - @VJ_Botz
11 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
12 | # Ask Doubt on telegram @KingVJ01
13 |
14 | @Client.on_message(filters.command(['link']))
15 | async def gen_link_s(client: Client, message):
16 | replied = message.reply_to_message
17 | if not replied:
18 | return await message.reply('Reply to a message to get a shareable link.')
19 | file_type = replied.media
20 | if file_type not in [enums.MessageMediaType.VIDEO, enums.MessageMediaType.AUDIO, enums.MessageMediaType.DOCUMENT]:
21 | return await message.reply("Reply to a supported media")
22 |
23 | # Don't Remove Credit Tg - @VJ_Botz
24 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
25 | # Ask Doubt on telegram @KingVJ01
26 |
27 | file_id = getattr(replied, file_type.value).file_id
28 | string = 'file_'
29 | string += file_id
30 | outstr = base64.urlsafe_b64encode(string.encode("ascii")).decode().strip("=")
31 | user_id = message.from_user.id
32 | user = await get_user(user_id)
33 | # Get the bot's username
34 | bot_username = (await client.get_me()).username
35 | share_link = f"https://t.me/{bot_username}?start={outstr}"
36 | if user["shortener_api"]:
37 | await message.reply(f"⭕ ʜᴇʀᴇ ɪs ʏᴏᴜʀ ʟɪɴᴋ:\n\n🔗 ᴏʀɪɢɪɴᴀʟ ʟɪɴᴋ :- {share_link}")
38 | else:
39 | short_link = await get_short_link(user, share_link)
40 | await message.reply(f"⭕ ʜᴇʀᴇ ɪs ʏᴏᴜʀ ʟɪɴᴋ:\n\n🖇️ sʜᴏʀᴛ ʟɪɴᴋ :- {short_link}")
41 |
42 |
43 | # Don't Remove Credit Tg - @VJ_Botz
44 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
45 | # Ask Doubt on telegram @KingVJ01
46 |
47 |
--------------------------------------------------------------------------------
/clone_plugins/users_api.py:
--------------------------------------------------------------------------------
1 | # © Telegram : @KingVJ01 , GitHub : @VJBots
2 |
3 | # Don't Remove Credit Tg - @VJ_Botz
4 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
5 | # Ask Doubt on telegram @KingVJ01
6 |
7 | import requests
8 | import json
9 | from motor.motor_asyncio import AsyncIOMotorClient
10 | from config import CLONE_DB_URI, CDB_NAME
11 |
12 | # Don't Remove Credit Tg - @VJ_Botz
13 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
14 | # Ask Doubt on telegram @KingVJ01
15 |
16 | client = AsyncIOMotorClient(CLONE_DB_URI)
17 | db = client[CDB_NAME]
18 | col = db["users"]
19 |
20 | # Don't Remove Credit Tg - @VJ_Botz
21 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
22 | # Ask Doubt on telegram @KingVJ01
23 |
24 | async def get_short_link(user, link):
25 | api_key = user["shortener_api"]
26 | base_site = user["base_site"]
27 | print(user)
28 | response = requests.get(f"https://{base_site}/api?api={api_key}&url={link}")
29 | data = response.json()
30 | if data["status"] == "success" or rget.status_code == 200:
31 | return data["shortenedUrl"]
32 |
33 | # Don't Remove Credit Tg - @VJ_Botz
34 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
35 | # Ask Doubt on telegram @KingVJ01
36 |
37 | async def get_user(user_id):
38 | user_id = int(user_id)
39 | user = await col.find_one({"user_id": user_id})
40 | if not user:
41 | res = {
42 | "user_id": user_id,
43 | "shortener_api": None,
44 | "base_site": None,
45 | }
46 | await col.insert_one(res)
47 | user = await col.find_one({"user_id": user_id})
48 | return user
49 |
50 | # Don't Remove Credit Tg - @VJ_Botz
51 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
52 | # Ask Doubt on telegram @KingVJ01
53 |
54 | async def update_user_info(user_id, value:dict):
55 | user_id = int(user_id)
56 | myquery = {"user_id": user_id}
57 | newvalues = { "$set": value }
58 | await col.update_one(myquery, newvalues)
59 |
60 | # Don't Remove Credit Tg - @VJ_Botz
61 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
62 | # Ask Doubt on telegram @KingVJ01
63 |
--------------------------------------------------------------------------------
/config.py:
--------------------------------------------------------------------------------
1 | # Don't Remove Credit Tg - @VJ_Botz
2 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
3 | # Ask Doubt on telegram @KingVJ01
4 |
5 |
6 | import re
7 | import os
8 | from os import environ
9 | from Script import script
10 |
11 | id_pattern = re.compile(r'^.\d+$')
12 | def is_enabled(value, default):
13 | if value.lower() in ["true", "yes", "1", "enable", "y"]:
14 | return True
15 | elif value.lower() in ["false", "no", "0", "disable", "n"]:
16 | return False
17 | else:
18 | return default
19 |
20 | # Bot Information
21 | API_ID = int(environ.get("API_ID", ""))
22 | API_HASH = environ.get("API_HASH", "")
23 | BOT_TOKEN = environ.get("BOT_TOKEN", "")
24 |
25 | PICS = (environ.get('PICS', 'https://graph.org/file/ce1723991756e48c35aa1.jpg')).split() # Bot Start Picture
26 | ADMINS = [int(admin) if id_pattern.search(admin) else admin for admin in environ.get('ADMINS', '').split()]
27 | BOT_USERNAME = environ.get("BOT_USERNAME", "") # without @
28 | PORT = environ.get("PORT", "8080")
29 |
30 | # Clone Info :-
31 | CLONE_MODE = bool(environ.get('CLONE_MODE', False)) # Set True or False
32 |
33 | # If Clone Mode Is True Then Fill All Required Variable, If False Then Don't Fill.
34 | CLONE_DB_URI = environ.get("CLONE_DB_URI", "")
35 | CDB_NAME = environ.get("CDB_NAME", "clonetechvj")
36 |
37 | # Database Information
38 | DB_URI = environ.get("DB_URI", "")
39 | DB_NAME = environ.get("DB_NAME", "techvjbotz")
40 |
41 | # Auto Delete Information
42 | AUTO_DELETE_MODE = bool(environ.get('AUTO_DELETE_MODE', True)) # Set True or False
43 |
44 | # If Auto Delete Mode Is True Then Fill All Required Variable, If False Then Don't Fill.
45 | AUTO_DELETE = int(environ.get("AUTO_DELETE", "30")) # Time in Minutes
46 | AUTO_DELETE_TIME = int(environ.get("AUTO_DELETE_TIME", "1800")) # Time in Seconds
47 |
48 | # Channel Information
49 | LOG_CHANNEL = int(environ.get("LOG_CHANNEL", ""))
50 |
51 | # File Caption Information
52 | CUSTOM_FILE_CAPTION = environ.get("CUSTOM_FILE_CAPTION", f"{script.CAPTION}")
53 | BATCH_FILE_CAPTION = environ.get("BATCH_FILE_CAPTION", CUSTOM_FILE_CAPTION)
54 |
55 | # Enable - True or Disable - False
56 | PUBLIC_FILE_STORE = is_enabled((environ.get('PUBLIC_FILE_STORE', "True")), True)
57 |
58 | # Verify Info :-
59 | VERIFY_MODE = bool(environ.get('VERIFY_MODE', False)) # Set True or False
60 |
61 | # If Verify Mode Is True Then Fill All Required Variable, If False Then Don't Fill.
62 | SHORTLINK_URL = environ.get("SHORTLINK_URL", "") # shortlink domain without https://
63 | SHORTLINK_API = environ.get("SHORTLINK_API", "") # shortlink api
64 | VERIFY_TUTORIAL = environ.get("VERIFY_TUTORIAL", "") # how to open link
65 |
66 | # Website Info:
67 | WEBSITE_URL_MODE = bool(environ.get('WEBSITE_URL_MODE', False)) # Set True or False
68 |
69 | # If Website Url Mode Is True Then Fill All Required Variable, If False Then Don't Fill.
70 | WEBSITE_URL = environ.get("WEBSITE_URL", "") # For More Information Check Video On Yt - @Tech_VJ
71 |
72 | # File Stream Config
73 | STREAM_MODE = bool(environ.get('STREAM_MODE', True)) # Set True or False
74 |
75 | # If Stream Mode Is True Then Fill All Required Variable, If False Then Don't Fill.
76 | MULTI_CLIENT = False
77 | SLEEP_THRESHOLD = int(environ.get('SLEEP_THRESHOLD', '60'))
78 | PING_INTERVAL = int(environ.get("PING_INTERVAL", "1200")) # 20 minutes
79 | if 'DYNO' in environ:
80 | ON_HEROKU = True
81 | else:
82 | ON_HEROKU = False
83 | URL = environ.get("URL", "https://testofvjfilter-1fa60b1b8498.herokuapp.com/")
84 |
85 |
86 | # Don't Remove Credit Tg - @VJ_Botz
87 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
88 | # Ask Doubt on telegram @KingVJ01
89 |
90 |
--------------------------------------------------------------------------------
/logging.conf:
--------------------------------------------------------------------------------
1 | [loggers]
2 | keys=root
3 |
4 | [handlers]
5 | keys=consoleHandler,fileHandler
6 |
7 | [formatters]
8 | keys=consoleFormatter,fileFormatter
9 |
10 | [logger_root]
11 | level=DEBUG
12 | handlers=consoleHandler,fileHandler
13 |
14 | [handler_consoleHandler]
15 | class=StreamHandler
16 | level=INFO
17 | formatter=consoleFormatter
18 | args=(sys.stdout,)
19 |
20 | [handler_fileHandler]
21 | class=FileHandler
22 | level=ERROR
23 | formatter=fileFormatter
24 | args=('TELEGRAM BOT.LOG','w',)
25 |
26 | [formatter_consoleFormatter]
27 | format=%(asctime)s - %(lineno)d - %(name)s - %(module)s - %(levelname)s - %(message)s
28 | datefmt=%I:%M:%S %p
29 |
30 | [formatter_fileFormatter]
31 | format=[%(asctime)s:%(name)s:%(lineno)d:%(levelname)s] %(message)s
32 | datefmt=%m/%d/%Y %I:%M:%S %p
33 |
--------------------------------------------------------------------------------
/plugins/TechVJ:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/plugins/broadcast.py:
--------------------------------------------------------------------------------
1 | # Don't Remove Credit Tg - @VJ_Botz
2 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
3 | # Ask Doubt on telegram @KingVJ01
4 |
5 | from pyrogram.errors import InputUserDeactivated, UserNotParticipant, FloodWait, UserIsBlocked, PeerIdInvalid
6 | from plugins.dbusers import db
7 | from pyrogram import Client, filters
8 | from config import ADMINS
9 | import asyncio
10 | import datetime
11 | import time
12 |
13 | # Don't Remove Credit Tg - @VJ_Botz
14 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
15 | # Ask Doubt on telegram @KingVJ01
16 |
17 | async def broadcast_messages(user_id, message):
18 | try:
19 | await message.copy(chat_id=user_id)
20 | return True, "Success"
21 | except FloodWait as e:
22 | await asyncio.sleep(e.value)
23 | return await broadcast_messages(user_id, message)
24 | except InputUserDeactivated:
25 | await db.delete_user(int(user_id))
26 | return False, "Deleted"
27 | except UserIsBlocked:
28 | await db.delete_user(int(user_id))
29 | return False, "Blocked"
30 | except PeerIdInvalid:
31 | await db.delete_user(int(user_id))
32 | return False, "Error"
33 | except Exception as e:
34 | return False, "Error"
35 |
36 | # Don't Remove Credit Tg - @VJ_Botz
37 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
38 | # Ask Doubt on telegram @KingVJ01
39 |
40 |
41 | @Client.on_message(filters.command("broadcast") & filters.user(ADMINS) & filters.reply)
42 | async def verupikkals(bot, message):
43 | users = await db.get_all_users()
44 | b_msg = message.reply_to_message
45 | sts = await message.reply_text(text='**Broadcasting your messages...**')
46 | start_time = time.time()
47 | total_users = await db.total_users_count()
48 | done = 0
49 | blocked = 0
50 | deleted = 0
51 | failed = 0
52 | success = 0
53 |
54 | # Don't Remove Credit Tg - @VJ_Botz
55 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
56 | # Ask Doubt on telegram @KingVJ01
57 |
58 | async for user in users:
59 | if 'id' in user:
60 | pti, sh = await broadcast_messages(int(user['id']), b_msg)
61 | if pti:
62 | success += 1
63 | elif pti == False:
64 | if sh == "Blocked":
65 | blocked += 1
66 | elif sh == "Deleted":
67 | deleted += 1
68 | elif sh == "Error":
69 | failed += 1
70 | done += 1
71 | if not done % 20:
72 | try:
73 | await sts.edit(f"Broadcast in progress:\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}")
74 | except:
75 | pass
76 | else:
77 | # Handle the case where 'id' key is missing in the user dictionary
78 | done += 1
79 | failed += 1
80 | if not done % 20:
81 | try:
82 | await sts.edit(f"Broadcast in progress:\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}")
83 | except:
84 | pass
85 |
86 | time_taken = datetime.timedelta(seconds=int(time.time()-start_time))
87 | await sts.edit(f"Broadcast Completed:\nCompleted in {time_taken} seconds.\n\nTotal Users {total_users}\nCompleted: {done} / {total_users}\nSuccess: {success}\nBlocked: {blocked}\nDeleted: {deleted}")
88 |
89 | # Don't Remove Credit Tg - @VJ_Botz
90 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
91 | # Ask Doubt on telegram @KingVJ01
92 |
93 |
--------------------------------------------------------------------------------
/plugins/clone.py:
--------------------------------------------------------------------------------
1 | # Don't Remove Credit Tg - @VJ_Botz
2 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
3 | # Ask Doubt on telegram @KingVJ01
4 |
5 | import re
6 | from pymongo import MongoClient
7 | from Script import script
8 | from pyrogram import Client, filters
9 | from pyrogram.types import Message
10 | from pyrogram.errors.exceptions.bad_request_400 import AccessTokenExpired, AccessTokenInvalid
11 | from config import API_ID, API_HASH, DB_URI, DB_NAME, CLONE_MODE
12 |
13 | mongo_client = MongoClient(DB_URI)
14 | mongo_db = mongo_client["cloned_vjbotz"]
15 |
16 | @Client.on_message(filters.command("clone") & filters.private)
17 | async def clone(client, message):
18 | if CLONE_MODE == False:
19 | return
20 | techvj = await client.ask(message.chat.id, "1) sᴇɴᴅ /newbot
ᴛᴏ @BotFather\n2) ɢɪᴠᴇ ᴀ ɴᴀᴍᴇ ꜰᴏʀ ʏᴏᴜʀ ʙᴏᴛ.\n3) ɢɪᴠᴇ ᴀ ᴜɴɪǫᴜᴇ ᴜsᴇʀɴᴀᴍᴇ.\n4) ᴛʜᴇɴ ʏᴏᴜ ᴡɪʟʟ ɢᴇᴛ ᴀ ᴍᴇssᴀɢᴇ ᴡɪᴛʜ ʏᴏᴜʀ ʙᴏᴛ ᴛᴏᴋᴇɴ.\n5) ꜰᴏʀᴡᴀʀᴅ ᴛʜᴀᴛ ᴍᴇssᴀɢᴇ ᴛᴏ ᴍᴇ.\n\n/cancel - ᴄᴀɴᴄᴇʟ ᴛʜɪs ᴘʀᴏᴄᴇss.")
21 | if techvj.text == '/cancel':
22 | await techvj.delete()
23 | return await message.reply('ᴄᴀɴᴄᴇʟᴇᴅ ᴛʜɪs ᴘʀᴏᴄᴇss 🚫')
24 | if techvj.forward_from and techvj.forward_from.id == 93372553:
25 | try:
26 | bot_token = re.findall(r"\b(\d+:[A-Za-z0-9_-]+)\b", techvj.text)[0]
27 | except:
28 | return await message.reply('sᴏᴍᴇᴛʜɪɴɢ ᴡᴇɴᴛ ᴡʀᴏɴɢ 😕')
29 | else:
30 | return await message.reply('ɴᴏᴛ ꜰᴏʀᴡᴀʀᴅᴇᴅ ꜰʀᴏᴍ @BotFather 😑')
31 | user_id = message.from_user.id
32 | msg = await message.reply_text("**👨💻 ᴡᴀɪᴛ ᴀ ᴍɪɴᴜᴛᴇ ɪ ᴀᴍ ᴄʀᴇᴀᴛɪɴɢ ʏᴏᴜʀ ʙᴏᴛ ❣️**")
33 | try:
34 | vj = Client(
35 | f"{bot_token}", API_ID, API_HASH,
36 | bot_token=bot_token,
37 | plugins={"root": "clone_plugins"}
38 | )
39 | await vj.start()
40 | bot = await vj.get_me()
41 | details = {
42 | 'bot_id': bot.id,
43 | 'is_bot': True,
44 | 'user_id': user_id,
45 | 'name': bot.first_name,
46 | 'token': bot_token,
47 | 'username': bot.username
48 | }
49 | mongo_db.bots.insert_one(details)
50 | await msg.edit_text(f"sᴜᴄᴄᴇssғᴜʟʟʏ ᴄʟᴏɴᴇᴅ ʏᴏᴜʀ ʙᴏᴛ: @{bot.username}.")
51 | except BaseException as e:
52 | await msg.edit_text(f"⚠️ Bot Error:\n\n{e}
\n\n**Kindly forward this message to @KingVJ01 to get assistance.**")
53 |
54 | @Client.on_message(filters.command("deletecloned") & filters.private)
55 | async def delete_cloned_bot(client, message):
56 | if CLONE_MODE == False:
57 | return
58 | try:
59 | techvj = await client.ask(message.chat.id, "**Send Me Bot Token To Delete**")
60 | bot_token = re.findall(r'\d[0-9]{8,10}:[0-9A-Za-z_-]{35}', techvj.text, re.IGNORECASE)
61 | bot_token = bot_token[0] if bot_token else None
62 | bot_id = re.findall(r'\d[0-9]{8,10}', techvj.text)
63 | cloned_bot = mongo_db.bots.find_one({"token": bot_token})
64 | if cloned_bot:
65 | mongo_db.bots.delete_one({"token": bot_token})
66 | await message.reply_text("**🤖 ᴛʜᴇ ᴄʟᴏɴᴇᴅ ʙᴏᴛ ʜᴀs ʙᴇᴇɴ ʀᴇᴍᴏᴠᴇᴅ ғʀᴏᴍ ᴛʜᴇ ʟɪsᴛ ᴀɴᴅ ɪᴛs ᴅᴇᴛᴀɪʟs ʜᴀᴠᴇ ʙᴇᴇɴ ʀᴇᴍᴏᴠᴇᴅ ғʀᴏᴍ ᴛʜᴇ ᴅᴀᴛᴀʙᴀsᴇ. ☠️**")
67 | else:
68 | await message.reply_text("**⚠️ ᴛʜᴇ ʙᴏᴛ ᴛᴏᴋᴇɴ ᴘʀᴏᴠɪᴅᴇᴅ ɪs ɴᴏᴛ ɪɴ ᴛʜᴇ ᴄʟᴏɴᴇᴅ ʟɪsᴛ.**")
69 | except:
70 | await message.reply_text("An error occurred while deleting the cloned bot.")
71 |
72 | # Don't Remove Credit Tg - @VJ_Botz
73 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
74 | # Ask Doubt on telegram @KingVJ01
75 |
76 | async def restart_bots():
77 | bots = list(mongo_db.bots.find())
78 | for bot in bots:
79 | bot_token = bot['token']
80 | try:
81 | vj = Client(
82 | f"{bot_token}", API_ID, API_HASH,
83 | bot_token=bot_token,
84 | plugins={"root": "clone_plugins"},
85 | )
86 | await vj.start()
87 | except:
88 | pass
89 |
--------------------------------------------------------------------------------
/plugins/commands.py:
--------------------------------------------------------------------------------
1 | # Don't Remove Credit Tg - @VJ_Botz
2 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
3 | # Ask Doubt on telegram @KingVJ01
4 |
5 | import os
6 | import logging
7 | import random
8 | import asyncio
9 | from validators import domain
10 | from Script import script
11 | from plugins.dbusers import db
12 | from pyrogram import Client, filters, enums
13 | from plugins.users_api import get_user, update_user_info
14 | from pyrogram.errors import ChatAdminRequired, FloodWait
15 | from pyrogram.types import *
16 | from utils import verify_user, check_token, check_verification, get_token
17 | from config import *
18 | import re
19 | import json
20 | import base64
21 | from urllib.parse import quote_plus
22 | from TechVJ.utils.file_properties import get_name, get_hash, get_media_file_size
23 | logger = logging.getLogger(__name__)
24 |
25 | BATCH_FILES = {}
26 |
27 | # Don't Remove Credit Tg - @VJ_Botz
28 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
29 | # Ask Doubt on telegram @KingVJ01
30 |
31 |
32 | def get_size(size):
33 | """Get size in readable format"""
34 |
35 | units = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB"]
36 | size = float(size)
37 | i = 0
38 | while size >= 1024.0 and i < len(units):
39 | i += 1
40 | size /= 1024.0
41 | return "%.2f %s" % (size, units[i])
42 |
43 | def formate_file_name(file_name):
44 | chars = ["[", "]", "(", ")"]
45 | for c in chars:
46 | file_name.replace(c, "")
47 | file_name = '@VJ_Botz ' + ' '.join(filter(lambda x: not x.startswith('http') and not x.startswith('@') and not x.startswith('www.'), file_name.split()))
48 | return file_name
49 |
50 | # Don't Remove Credit Tg - @VJ_Botz
51 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
52 | # Ask Doubt on telegram @KingVJ0
53 |
54 |
55 | @Client.on_message(filters.command("start") & filters.incoming)
56 | async def start(client, message):
57 | username = client.me.username
58 | if not await db.is_user_exist(message.from_user.id):
59 | await db.add_user(message.from_user.id, message.from_user.first_name)
60 | await client.send_message(LOG_CHANNEL, script.LOG_TEXT.format(message.from_user.id, message.from_user.mention))
61 | if len(message.command) != 2:
62 | buttons = [[
63 | InlineKeyboardButton('💝 sᴜʙsᴄʀɪʙᴇ ᴍʏ ʏᴏᴜᴛᴜʙᴇ ᴄʜᴀɴɴᴇʟ', url='https://youtube.com/@Tech_VJ')
64 | ],[
65 | InlineKeyboardButton('🔍 sᴜᴘᴘᴏʀᴛ ɢʀᴏᴜᴘ', url='https://t.me/vj_bot_disscussion'),
66 | InlineKeyboardButton('🤖 ᴜᴘᴅᴀᴛᴇ ᴄʜᴀɴɴᴇʟ', url='https://t.me/vj_botz')
67 | ],[
68 | InlineKeyboardButton('💁♀️ ʜᴇʟᴘ', callback_data='help'),
69 | InlineKeyboardButton('😊 ᴀʙᴏᴜᴛ', callback_data='about')
70 | ]]
71 | if CLONE_MODE == True:
72 | buttons.append([InlineKeyboardButton('🤖 ᴄʀᴇᴀᴛᴇ ʏᴏᴜʀ ᴏᴡɴ ᴄʟᴏɴᴇ ʙᴏᴛ', callback_data='clone')])
73 | reply_markup = InlineKeyboardMarkup(buttons)
74 | me = client.me
75 | await message.reply_photo(
76 | photo=random.choice(PICS),
77 | caption=script.START_TXT.format(message.from_user.mention, me.mention),
78 | reply_markup=reply_markup
79 | )
80 | return
81 |
82 | # Don't Remove Credit Tg - @VJ_Botz
83 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
84 | # Ask Doubt on telegram @KingVJ01
85 |
86 | data = message.command[1]
87 | try:
88 | pre, file_id = data.split('_', 1)
89 | except:
90 | file_id = data
91 | pre = ""
92 | if data.split("-", 1)[0] == "verify":
93 | userid = data.split("-", 2)[1]
94 | token = data.split("-", 3)[2]
95 | if str(message.from_user.id) != str(userid):
96 | return await message.reply_text(
97 | text="Invalid link or Expired link !",
98 | protect_content=True
99 | )
100 | is_valid = await check_token(client, userid, token)
101 | if is_valid == True:
102 | await message.reply_text(
103 | text=f"Hey {message.from_user.mention}, You are successfully verified !\nNow you have unlimited access for all files till today midnight.",
104 | protect_content=True
105 | )
106 | await verify_user(client, userid, token)
107 | else:
108 | return await message.reply_text(
109 | text="Invalid link or Expired link !",
110 | protect_content=True
111 | )
112 | elif data.split("-", 1)[0] == "BATCH":
113 | try:
114 | if not await check_verification(client, message.from_user.id) and VERIFY_MODE == True:
115 | btn = [[
116 | InlineKeyboardButton("Verify", url=await get_token(client, message.from_user.id, f"https://telegram.me/{username}?start="))
117 | ],[
118 | InlineKeyboardButton("How To Open Link & Verify", url=VERIFY_TUTORIAL)
119 | ]]
120 | await message.reply_text(
121 | text="You are not verified !\nKindly verify to continue !",
122 | protect_content=True,
123 | reply_markup=InlineKeyboardMarkup(btn)
124 | )
125 | return
126 | except Exception as e:
127 | return await message.reply_text(f"**Error - {e}**")
128 | sts = await message.reply("**🔺 ᴘʟᴇᴀsᴇ ᴡᴀɪᴛ**")
129 | file_id = data.split("-", 1)[1]
130 | msgs = BATCH_FILES.get(file_id)
131 | if not msgs:
132 | decode_file_id = base64.urlsafe_b64decode(file_id + "=" * (-len(file_id) % 4)).decode("ascii")
133 | msg = await client.get_messages(LOG_CHANNEL, int(decode_file_id))
134 | media = getattr(msg, msg.media.value)
135 | file_id = media.file_id
136 | file = await client.download_media(file_id)
137 | try:
138 | with open(file) as file_data:
139 | msgs=json.loads(file_data.read())
140 | except:
141 | await sts.edit("FAILED")
142 | return await client.send_message(LOG_CHANNEL, "UNABLE TO OPEN FILE.")
143 | os.remove(file)
144 | BATCH_FILES[file_id] = msgs
145 |
146 | filesarr = []
147 | for msg in msgs:
148 | channel_id = int(msg.get("channel_id"))
149 | msgid = msg.get("msg_id")
150 | info = await client.get_messages(channel_id, int(msgid))
151 | if info.media:
152 | file_type = info.media
153 | file = getattr(info, file_type.value)
154 | f_caption = getattr(info, 'caption', '')
155 | if f_caption:
156 | f_caption = f_caption.html
157 | old_title = getattr(file, "file_name", "")
158 | title = formate_file_name(old_title)
159 | size=get_size(int(file.file_size))
160 | if BATCH_FILE_CAPTION:
161 | try:
162 | f_caption=BATCH_FILE_CAPTION.format(file_name= '' if title is None else title, file_size='' if size is None else size, file_caption='' if f_caption is None else f_caption)
163 | except:
164 | f_caption=f_caption
165 | if f_caption is None:
166 | f_caption = f"{title}"
167 | if STREAM_MODE == True:
168 | if info.video or info.document:
169 | log_msg = info
170 | fileName = {quote_plus(get_name(log_msg))}
171 | stream = f"{URL}watch/{str(log_msg.id)}/{quote_plus(get_name(log_msg))}?hash={get_hash(log_msg)}"
172 | download = f"{URL}{str(log_msg.id)}/{quote_plus(get_name(log_msg))}?hash={get_hash(log_msg)}"
173 | button = [[
174 | InlineKeyboardButton("• ᴅᴏᴡɴʟᴏᴀᴅ •", url=download),
175 | InlineKeyboardButton('• ᴡᴀᴛᴄʜ •', url=stream)
176 | ],[
177 | InlineKeyboardButton("• ᴡᴀᴛᴄʜ ɪɴ ᴡᴇʙ ᴀᴘᴘ •", web_app=WebAppInfo(url=stream))
178 | ]]
179 | reply_markup=InlineKeyboardMarkup(button)
180 | else:
181 | reply_markup = None
182 | try:
183 | msg = await info.copy(chat_id=message.from_user.id, caption=f_caption, protect_content=False, reply_markup=reply_markup)
184 | except FloodWait as e:
185 | await asyncio.sleep(e.value)
186 | msg = await info.copy(chat_id=message.from_user.id, caption=f_caption, protect_content=False, reply_markup=reply_markup)
187 | except:
188 | continue
189 | else:
190 | try:
191 | msg = await info.copy(chat_id=message.from_user.id, protect_content=False)
192 | except FloodWait as e:
193 | await asyncio.sleep(e.value)
194 | msg = await info.copy(chat_id=message.from_user.id, protect_content=False)
195 | except:
196 | continue
197 | filesarr.append(msg)
198 | await asyncio.sleep(1)
199 | await sts.delete()
200 | if AUTO_DELETE_MODE == True:
201 | k = await client.send_message(chat_id = message.from_user.id, text=f"❗️❗️❗️IMPORTANT❗️️❗️❗️\n\nThis Movie File/Video will be deleted in {AUTO_DELETE} minutes 🫥 (Due to Copyright Issues).\n\nPlease forward this File/Video to your Saved Messages and Start Download there")
202 | await asyncio.sleep(AUTO_DELETE_TIME)
203 | for x in filesarr:
204 | try:
205 | await x.delete()
206 | except:
207 | pass
208 | await k.edit_text("Your All Files/Videos is successfully deleted!!!")
209 | return
210 |
211 | # Don't Remove Credit Tg - @VJ_Botz
212 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
213 | # Ask Doubt on telegram @KingVJ01
214 |
215 | pre, decode_file_id = ((base64.urlsafe_b64decode(data + "=" * (-len(data) % 4))).decode("ascii")).split("_", 1)
216 | if not await check_verification(client, message.from_user.id) and VERIFY_MODE == True:
217 | btn = [[
218 | InlineKeyboardButton("Verify", url=await get_token(client, message.from_user.id, f"https://telegram.me/{username}?start="))
219 | ],[
220 | InlineKeyboardButton("How To Open Link & Verify", url=VERIFY_TUTORIAL)
221 | ]]
222 | await message.reply_text(
223 | text="You are not verified !\nKindly verify to continue !",
224 | protect_content=True,
225 | reply_markup=InlineKeyboardMarkup(btn)
226 | )
227 | return
228 | try:
229 | msg = await client.get_messages(LOG_CHANNEL, int(decode_file_id))
230 | if msg.media:
231 | media = getattr(msg, msg.media.value)
232 | title = formate_file_name(media.file_name)
233 | size=get_size(media.file_size)
234 | f_caption = f"{title}
"
235 | if CUSTOM_FILE_CAPTION:
236 | try:
237 | f_caption=CUSTOM_FILE_CAPTION.format(file_name= '' if title is None else title, file_size='' if size is None else size, file_caption='')
238 | except:
239 | return
240 | if STREAM_MODE == True:
241 | if msg.video or msg.document:
242 | log_msg = msg
243 | fileName = {quote_plus(get_name(log_msg))}
244 | stream = f"{URL}watch/{str(log_msg.id)}/{quote_plus(get_name(log_msg))}?hash={get_hash(log_msg)}"
245 | download = f"{URL}{str(log_msg.id)}/{quote_plus(get_name(log_msg))}?hash={get_hash(log_msg)}"
246 | button = [[
247 | InlineKeyboardButton("• ᴅᴏᴡɴʟᴏᴀᴅ •", url=download),
248 | InlineKeyboardButton('• ᴡᴀᴛᴄʜ •', url=stream)
249 | ],[
250 | InlineKeyboardButton("• ᴡᴀᴛᴄʜ ɪɴ ᴡᴇʙ ᴀᴘᴘ •", web_app=WebAppInfo(url=stream))
251 | ]]
252 | reply_markup=InlineKeyboardMarkup(button)
253 | else:
254 | reply_markup = None
255 | del_msg = await msg.copy(chat_id=message.from_user.id, caption=f_caption, reply_markup=reply_markup, protect_content=False)
256 | else:
257 | del_msg = await msg.copy(chat_id=message.from_user.id, protect_content=False)
258 | if AUTO_DELETE_MODE == True:
259 | k = await client.send_message(chat_id = message.from_user.id, text=f"❗️❗️❗️IMPORTANT❗️️❗️❗️\n\nThis Movie File/Video will be deleted in {AUTO_DELETE} minutes 🫥 (Due to Copyright Issues).\n\nPlease forward this File/Video to your Saved Messages and Start Download there")
260 | await asyncio.sleep(AUTO_DELETE_TIME)
261 | try:
262 | await del_msg.delete()
263 | except:
264 | pass
265 | await k.edit_text("Your File/Video is successfully deleted!!!")
266 | return
267 | except:
268 | pass
269 |
270 | # Don't Remove Credit Tg - @VJ_Botz
271 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
272 | # Ask Doubt on telegram @KingVJ01
273 |
274 | @Client.on_message(filters.command('api') & filters.private)
275 | async def shortener_api_handler(client, m: Message):
276 | user_id = m.from_user.id
277 | user = await get_user(user_id)
278 | cmd = m.command
279 |
280 | if len(cmd) == 1:
281 | s = script.SHORTENER_API_MESSAGE.format(base_site=user["base_site"], shortener_api=user["shortener_api"])
282 | return await m.reply(s)
283 |
284 | elif len(cmd) == 2:
285 | api = cmd[1].strip()
286 | await update_user_info(user_id, {"shortener_api": api})
287 | await m.reply("Shortener API updated successfully to " + api)
288 |
289 | # Don't Remove Credit Tg - @VJ_Botz
290 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
291 | # Ask Doubt on telegram @KingVJ01
292 |
293 | @Client.on_message(filters.command("base_site") & filters.private)
294 | async def base_site_handler(client, m: Message):
295 | user_id = m.from_user.id
296 | user = await get_user(user_id)
297 | cmd = m.command
298 | text = f"`/base_site (base_site)`\n\nCurrent base site: None\n\n EX: `/base_site shortnerdomain.com`\n\nIf You Want To Remove Base Site Then Copy This And Send To Bot - `/base_site None`"
299 | if len(cmd) == 1:
300 | return await m.reply(text=text, disable_web_page_preview=True)
301 | elif len(cmd) == 2:
302 | base_site = cmd[1].strip()
303 | if base_site == None:
304 | await update_user_info(user_id, {"base_site": base_site})
305 | return await m.reply("Base Site updated successfully")
306 |
307 | if not domain(base_site):
308 | return await m.reply(text=text, disable_web_page_preview=True)
309 | await update_user_info(user_id, {"base_site": base_site})
310 | await m.reply("Base Site updated successfully")
311 |
312 | # Don't Remove Credit Tg - @VJ_Botz
313 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
314 | # Ask Doubt on telegram @KingVJ01
315 |
316 | @Client.on_callback_query()
317 | async def cb_handler(client: Client, query: CallbackQuery):
318 | if query.data == "close_data":
319 | await query.message.delete()
320 | elif query.data == "about":
321 | buttons = [[
322 | InlineKeyboardButton('Hᴏᴍᴇ', callback_data='start'),
323 | InlineKeyboardButton('🔒 Cʟᴏsᴇ', callback_data='close_data')
324 | ]]
325 | await client.edit_message_media(
326 | query.message.chat.id,
327 | query.message.id,
328 | InputMediaPhoto(random.choice(PICS))
329 | )
330 | reply_markup = InlineKeyboardMarkup(buttons)
331 | me2 = (await client.get_me()).mention
332 | await query.message.edit_text(
333 | text=script.ABOUT_TXT.format(me2),
334 | reply_markup=reply_markup,
335 | parse_mode=enums.ParseMode.HTML
336 | )
337 |
338 | # Don't Remove Credit Tg - @VJ_Botz
339 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
340 | # Ask Doubt on telegram @KingVJ01
341 |
342 | elif query.data == "start":
343 | buttons = [[
344 | InlineKeyboardButton('💝 sᴜʙsᴄʀɪʙᴇ ᴍʏ ʏᴏᴜᴛᴜʙᴇ ᴄʜᴀɴɴᴇʟ', url='https://youtube.com/@Tech_VJ')
345 | ],[
346 | InlineKeyboardButton('🔍 sᴜᴘᴘᴏʀᴛ ɢʀᴏᴜᴘ', url='https://t.me/vj_bot_disscussion'),
347 | InlineKeyboardButton('🤖 ᴜᴘᴅᴀᴛᴇ ᴄʜᴀɴɴᴇʟ', url='https://t.me/vj_botz')
348 | ],[
349 | InlineKeyboardButton('💁♀️ ʜᴇʟᴘ', callback_data='help'),
350 | InlineKeyboardButton('😊 ᴀʙᴏᴜᴛ', callback_data='about')
351 | ]]
352 | if CLONE_MODE == True:
353 | buttons.append([InlineKeyboardButton('🤖 ᴄʀᴇᴀᴛᴇ ʏᴏᴜʀ ᴏᴡɴ ᴄʟᴏɴᴇ ʙᴏᴛ', callback_data='clone')])
354 | reply_markup = InlineKeyboardMarkup(buttons)
355 | await client.edit_message_media(
356 | query.message.chat.id,
357 | query.message.id,
358 | InputMediaPhoto(random.choice(PICS))
359 | )
360 | me2 = (await client.get_me()).mention
361 | await query.message.edit_text(
362 | text=script.START_TXT.format(query.from_user.mention, me2),
363 | reply_markup=reply_markup,
364 | parse_mode=enums.ParseMode.HTML
365 | )
366 |
367 | # Don't Remove Credit Tg - @VJ_Botz
368 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
369 | # Ask Doubt on telegram @KingVJ01
370 |
371 | elif query.data == "clone":
372 | buttons = [[
373 | InlineKeyboardButton('Hᴏᴍᴇ', callback_data='start'),
374 | InlineKeyboardButton('🔒 Cʟᴏsᴇ', callback_data='close_data')
375 | ]]
376 | await client.edit_message_media(
377 | query.message.chat.id,
378 | query.message.id,
379 | InputMediaPhoto(random.choice(PICS))
380 | )
381 | reply_markup = InlineKeyboardMarkup(buttons)
382 | await query.message.edit_text(
383 | text=script.CLONE_TXT.format(query.from_user.mention),
384 | reply_markup=reply_markup,
385 | parse_mode=enums.ParseMode.HTML
386 | )
387 |
388 | # Don't Remove Credit Tg - @VJ_Botz
389 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
390 | # Ask Doubt on telegram @KingVJ01
391 |
392 | elif query.data == "help":
393 | buttons = [[
394 | InlineKeyboardButton('Hᴏᴍᴇ', callback_data='start'),
395 | InlineKeyboardButton('🔒 Cʟᴏsᴇ', callback_data='close_data')
396 | ]]
397 | await client.edit_message_media(
398 | query.message.chat.id,
399 | query.message.id,
400 | InputMediaPhoto(random.choice(PICS))
401 | )
402 | reply_markup = InlineKeyboardMarkup(buttons)
403 | await query.message.edit_text(
404 | text=script.HELP_TXT,
405 | reply_markup=reply_markup,
406 | parse_mode=enums.ParseMode.HTML
407 | )
408 |
409 | # Don't Remove Credit Tg - @VJ_Botz
410 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
411 | # Ask Doubt on telegram @KingVJ01
412 |
--------------------------------------------------------------------------------
/plugins/dbusers.py:
--------------------------------------------------------------------------------
1 | import motor.motor_asyncio
2 | from config import DB_NAME, DB_URI
3 |
4 | class Database:
5 |
6 | def __init__(self, uri, database_name):
7 | self._client = motor.motor_asyncio.AsyncIOMotorClient(uri)
8 | self.db = self._client[database_name]
9 | self.col = self.db.users
10 |
11 | def new_user(self, id, name):
12 | return dict(
13 | id = id,
14 | name = name,
15 | )
16 |
17 | async def add_user(self, id, name):
18 | user = self.new_user(id, name)
19 | await self.col.insert_one(user)
20 |
21 | async def is_user_exist(self, id):
22 | user = await self.col.find_one({'id':int(id)})
23 | return bool(user)
24 |
25 | async def total_users_count(self):
26 | count = await self.col.count_documents({})
27 | return count
28 |
29 | async def get_all_users(self):
30 | return self.col.find({})
31 |
32 | async def delete_user(self, user_id):
33 | await self.col.delete_many({'id': int(user_id)})
34 |
35 |
36 | db = Database(DB_URI, DB_NAME)
37 |
--------------------------------------------------------------------------------
/plugins/genlink.py:
--------------------------------------------------------------------------------
1 | # Don't Remove Credit @VJ_Botz
2 | # Subscribe YouTube Channel For Amazing Bot @Tech_VJ
3 | # Ask Doubt on telegram @KingVJ01
4 |
5 | import re
6 | from pyrogram import filters, Client, enums
7 | from pyrogram.errors.exceptions.bad_request_400 import ChannelInvalid, UsernameInvalid, UsernameNotModified
8 | from config import ADMINS, LOG_CHANNEL, PUBLIC_FILE_STORE, WEBSITE_URL, WEBSITE_URL_MODE
9 | from plugins.users_api import get_user, get_short_link
10 | import re
11 | import os
12 | import json
13 | import base64
14 |
15 | # Don't Remove Credit Tg - @VJ_Botz
16 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
17 | # Ask Doubt on telegram @KingVJ01
18 |
19 | async def allowed(_, __, message):
20 | if PUBLIC_FILE_STORE:
21 | return True
22 | if message.from_user and message.from_user.id in ADMINS:
23 | return True
24 | return False
25 |
26 | # Don't Remove Credit Tg - @VJ_Botz
27 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
28 | # Ask Doubt on telegram @KingVJ01
29 |
30 | @Client.on_message((filters.document | filters.video | filters.audio) & filters.private & filters.create(allowed))
31 | async def incoming_gen_link(bot, message):
32 | username = (await bot.get_me()).username
33 | file_type = message.media
34 | post = await message.copy(LOG_CHANNEL)
35 | file_id = str(post.id)
36 | string = 'file_'
37 | string += file_id
38 | outstr = base64.urlsafe_b64encode(string.encode("ascii")).decode().strip("=")
39 | user_id = message.from_user.id
40 | user = await get_user(user_id)
41 | if WEBSITE_URL_MODE == True:
42 | share_link = f"{WEBSITE_URL}?Tech_VJ={outstr}"
43 | else:
44 | share_link = f"https://t.me/{username}?start={outstr}"
45 | if user["base_site"] and user["shortener_api"] != None:
46 | short_link = await get_short_link(user, share_link)
47 | await message.reply(f"⭕ ʜᴇʀᴇ ɪs ʏᴏᴜʀ ʟɪɴᴋ:\n\n🖇️ sʜᴏʀᴛ ʟɪɴᴋ :- {short_link}")
48 | else:
49 | await message.reply(f"⭕ ʜᴇʀᴇ ɪs ʏᴏᴜʀ ʟɪɴᴋ:\n\n🔗 ᴏʀɪɢɪɴᴀʟ ʟɪɴᴋ :- {share_link}")
50 |
51 |
52 | @Client.on_message(filters.command(['link']) & filters.create(allowed))
53 | async def gen_link_s(bot, message):
54 | username = (await bot.get_me()).username
55 | replied = message.reply_to_message
56 | if not replied:
57 | return await message.reply('Reply to a message to get a shareable link.')
58 | # Don't Remove Credit Tg - @VJ_Botz
59 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
60 | # Ask Doubt on telegram @KingVJ01
61 |
62 | post = await replied.copy(LOG_CHANNEL)
63 | file_id = str(post.id)
64 | string = f"file_"
65 | string += file_id
66 | outstr = base64.urlsafe_b64encode(string.encode("ascii")).decode().strip("=")
67 | user_id = message.from_user.id
68 | user = await get_user(user_id)
69 | if WEBSITE_URL_MODE == True:
70 | share_link = f"{WEBSITE_URL}?Tech_VJ={outstr}"
71 | else:
72 | share_link = f"https://t.me/{username}?start={outstr}"
73 | if user["base_site"] and user["shortener_api"] != None:
74 | short_link = await get_short_link(user, share_link)
75 | await message.reply(f"⭕ ʜᴇʀᴇ ɪs ʏᴏᴜʀ ʟɪɴᴋ:\n\n🖇️ sʜᴏʀᴛ ʟɪɴᴋ :- {short_link}")
76 | else:
77 | await message.reply(f"⭕ ʜᴇʀᴇ ɪs ʏᴏᴜʀ ʟɪɴᴋ:\n\n🔗 ᴏʀɪɢɪɴᴀʟ ʟɪɴᴋ :- {share_link}")
78 |
79 |
80 | # Don't Remove Credit Tg - @VJ_Botz
81 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
82 | # Ask Doubt on telegram @KingVJ01
83 |
84 | @Client.on_message(filters.command(['batch']) & filters.create(allowed))
85 | async def gen_link_batch(bot, message):
86 | username = (await bot.get_me()).username
87 | if " " not in message.text:
88 | return await message.reply("Use correct format.\nExample /batch https://t.me/vj_botz/10 https://t.me/vj_botz/20.")
89 | links = message.text.strip().split(" ")
90 | if len(links) != 3:
91 | return await message.reply("Use correct format.\nExample /batch https://t.me/vj_botz/10 https://t.me/vj_botz/20.")
92 | cmd, first, last = links
93 | regex = re.compile("(https://)?(t\.me/|telegram\.me/|telegram\.dog/)(c/)?(\d+|[a-zA-Z_0-9]+)/(\d+)$")
94 | match = regex.match(first)
95 | if not match:
96 | return await message.reply('Invalid link')
97 | f_chat_id = match.group(4)
98 | f_msg_id = int(match.group(5))
99 | if f_chat_id.isnumeric():
100 | f_chat_id = int(("-100" + f_chat_id))
101 |
102 | # Don't Remove Credit Tg - @VJ_Botz
103 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
104 | # Ask Doubt on telegram @KingVJ01
105 |
106 | match = regex.match(last)
107 | if not match:
108 | return await message.reply('Invalid link')
109 | l_chat_id = match.group(4)
110 | l_msg_id = int(match.group(5))
111 | if l_chat_id.isnumeric():
112 | l_chat_id = int(("-100" + l_chat_id))
113 |
114 | if f_chat_id != l_chat_id:
115 | return await message.reply("Chat ids not matched.")
116 | try:
117 | chat_id = (await bot.get_chat(f_chat_id)).id
118 | except ChannelInvalid:
119 | return await message.reply('This may be a private channel / group. Make me an admin over there to index the files.')
120 | except (UsernameInvalid, UsernameNotModified):
121 | return await message.reply('Invalid Link specified.')
122 | except Exception as e:
123 | return await message.reply(f'Errors - {e}')
124 |
125 | # Don't Remove Credit Tg - @VJ_Botz
126 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
127 | # Ask Doubt on telegram @KingVJ01
128 |
129 | sts = await message.reply("**ɢᴇɴᴇʀᴀᴛɪɴɢ ʟɪɴᴋ ғᴏʀ ʏᴏᴜʀ ᴍᴇssᴀɢᴇ**.\n**ᴛʜɪs ᴍᴀʏ ᴛᴀᴋᴇ ᴛɪᴍᴇ ᴅᴇᴘᴇɴᴅɪɴɢ ᴜᴘᴏɴ ɴᴜᴍʙᴇʀ ᴏғ ᴍᴇssᴀɢᴇs**")
130 |
131 | FRMT = "**ɢᴇɴᴇʀᴀᴛɪɴɢ ʟɪɴᴋ...**\n**ᴛᴏᴛᴀʟ ᴍᴇssᴀɢᴇs:** {total}\n**ᴅᴏɴᴇ:** {current}\n**ʀᴇᴍᴀɪɴɪɴɢ:** {rem}\n**sᴛᴀᴛᴜs:** {sts}"
132 |
133 | outlist = []
134 |
135 | # Don't Remove Credit Tg - @VJ_Botz
136 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
137 | # Ask Doubt on telegram @KingVJ01
138 |
139 | # file store without db channel
140 | og_msg = 0
141 | tot = 0
142 | async for msg in bot.iter_messages(f_chat_id, l_msg_id, f_msg_id):
143 | tot += 1
144 | if og_msg % 20 == 0:
145 | try:
146 | await sts.edit(FRMT.format(total=l_msg_id-f_msg_id, current=tot, rem=((l_msg_id-f_msg_id) - tot), sts="Saving Messages"))
147 | except:
148 | pass
149 | if msg.empty or msg.service:
150 | continue
151 | file = {
152 | "channel_id": f_chat_id,
153 | "msg_id": msg.id
154 | }
155 | og_msg +=1
156 | outlist.append(file)
157 |
158 | # Don't Remove Credit Tg - @VJ_Botz
159 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
160 | # Ask Doubt on telegram @KingVJ01
161 |
162 | with open(f"batchmode_{message.from_user.id}.json", "w+") as out:
163 | json.dump(outlist, out)
164 | post = await bot.send_document(LOG_CHANNEL, f"batchmode_{message.from_user.id}.json", file_name="Batch.json", caption="⚠️ Batch Generated For Filestore.")
165 | os.remove(f"batchmode_{message.from_user.id}.json")
166 | string = str(post.id)
167 | file_id = base64.urlsafe_b64encode(string.encode("ascii")).decode().strip("=")
168 | user_id = message.from_user.id
169 | user = await get_user(user_id)
170 | if WEBSITE_URL_MODE == True:
171 | share_link = f"{WEBSITE_URL}?Tech_VJ=BATCH-{file_id}"
172 | else:
173 | share_link = f"https://t.me/{username}?start=BATCH-{file_id}"
174 | if user["base_site"] and user["shortener_api"] != None:
175 | short_link = await get_short_link(user, share_link)
176 | await sts.edit(f"⭕ ʜᴇʀᴇ ɪs ʏᴏᴜʀ ʟɪɴᴋ:\n\nContains `{og_msg}` files.\n\n🖇️ sʜᴏʀᴛ ʟɪɴᴋ :- {short_link}")
177 | else:
178 | await sts.edit(f"⭕ ʜᴇʀᴇ ɪs ʏᴏᴜʀ ʟɪɴᴋ:\n\nContains `{og_msg}` files.\n\n🔗 ᴏʀɪɢɪɴᴀʟ ʟɪɴᴋ :- {share_link}")
179 |
180 | # Don't Remove Credit Tg - @VJ_Botz
181 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
182 | # Ask Doubt on telegram @KingVJ01
183 |
184 |
--------------------------------------------------------------------------------
/plugins/users_api.py:
--------------------------------------------------------------------------------
1 | # © Telegram : @KingVJ01 , GitHub : @VJBots
2 |
3 | # Don't Remove Credit Tg - @VJ_Botz
4 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
5 | # Ask Doubt on telegram @KingVJ01
6 |
7 | import requests
8 | import json
9 | from motor.motor_asyncio import AsyncIOMotorClient
10 | from plugins.clone import mongo_db
11 |
12 | # Don't Remove Credit Tg - @VJ_Botz
13 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
14 | # Ask Doubt on telegram @KingVJ01
15 |
16 | async def get_short_link(user, link):
17 | api_key = user["shortener_api"]
18 | base_site = user["base_site"]
19 | print(user)
20 | response = requests.get(f"https://{base_site}/api?api={api_key}&url={link}")
21 | data = response.json()
22 | if data["status"] == "success" or rget.status_code == 200:
23 | return data["shortenedUrl"]
24 |
25 | # Don't Remove Credit Tg - @VJ_Botz
26 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
27 | # Ask Doubt on telegram @KingVJ01
28 |
29 | async def get_user(user_id):
30 | user_id = int(user_id)
31 | user = mongo_db.user.find_one({"user_id": user_id})
32 | if not user:
33 | res = {
34 | "user_id": user_id,
35 | "shortener_api": None,
36 | "base_site": None,
37 | }
38 | mongo_db.user.insert_one(res)
39 | user = mongo_db.user.find_one({"user_id": user_id})
40 | return user
41 |
42 | # Don't Remove Credit Tg - @VJ_Botz
43 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
44 | # Ask Doubt on telegram @KingVJ01
45 |
46 | async def update_user_info(user_id, value:dict):
47 | user_id = int(user_id)
48 | myquery = {"user_id": user_id}
49 | newvalues = { "$set": value }
50 | mongo_db.user.update_one(myquery, newvalues)
51 |
52 | # Don't Remove Credit Tg - @VJ_Botz
53 | # Subscribe YouTube Channel For Amazing Bot https://youtube.com/@Tech_VJ
54 | # Ask Doubt on telegram @KingVJ01
55 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | pyrofork==2.3.45
2 | Tgcrypto
3 | asyncio
4 | aiohttp
5 | pymongo[srv]==3.12.3
6 | motor==2.5.1
7 | marshmallow==3.14.1
8 | umongo==3.0.1
9 | validators
10 | requests
11 | bs4
12 | pytz
13 | shortzy
14 | python-dotenv==0.21.1
15 | Flask==1.1.2
16 | gunicorn==20.1.0
17 | Jinja2==3.0.3
18 | werkzeug==2.0.2
19 | itsdangerous==2.0.1
20 |
--------------------------------------------------------------------------------
/run cmd.txt:
--------------------------------------------------------------------------------
1 | gunicorn app:app & python3 bot.py
2 |
--------------------------------------------------------------------------------
/runtime.txt:
--------------------------------------------------------------------------------
1 | python-3.10.8
2 |
--------------------------------------------------------------------------------
/utils.py:
--------------------------------------------------------------------------------
1 | import logging, asyncio, os, re, random, pytz, aiohttp, requests, string, json, http.client
2 | from datetime import date, datetime
3 | from config import SHORTLINK_API, SHORTLINK_URL
4 | from shortzy import Shortzy
5 |
6 | logger = logging.getLogger(__name__)
7 | logger.setLevel(logging.INFO)
8 | TOKENS = {}
9 | VERIFIED = {}
10 |
11 | async def get_verify_shorted_link(link):
12 | if SHORTLINK_URL == "api.shareus.io":
13 | url = f'https://{SHORTLINK_URL}/easy_api'
14 | params = {
15 | "key": SHORTLINK_API,
16 | "link": link,
17 | }
18 | try:
19 | async with aiohttp.ClientSession() as session:
20 | async with session.get(url, params=params, raise_for_status=True, ssl=False) as response:
21 | data = await response.text()
22 | return data
23 | except Exception as e:
24 | logger.error(e)
25 | return link
26 | else:
27 | # response = requests.get(f"https://{SHORTLINK_URL}/api?api={SHORTLINK_API}&url={link}")
28 | # data = response.json()
29 | # if data["status"] == "success" or rget.status_code == 200:
30 | # return data["shortenedUrl"]
31 | shortzy = Shortzy(api_key=SHORTLINK_API, base_site=SHORTLINK_URL)
32 | link = await shortzy.convert(link)
33 | return link
34 |
35 | async def check_token(bot, userid, token):
36 | user = await bot.get_users(userid)
37 | if user.id in TOKENS.keys():
38 | TKN = TOKENS[user.id]
39 | if token in TKN.keys():
40 | is_used = TKN[token]
41 | if is_used == True:
42 | return False
43 | else:
44 | return True
45 | else:
46 | return False
47 |
48 | async def get_token(bot, userid, link):
49 | user = await bot.get_users(userid)
50 | token = ''.join(random.choices(string.ascii_letters + string.digits, k=7))
51 | TOKENS[user.id] = {token: False}
52 | link = f"{link}verify-{user.id}-{token}"
53 | shortened_verify_url = await get_verify_shorted_link(link)
54 | return str(shortened_verify_url)
55 |
56 | async def verify_user(bot, userid, token):
57 | user = await bot.get_users(userid)
58 | TOKENS[user.id] = {token: True}
59 | tz = pytz.timezone('Asia/Kolkata')
60 | today = date.today()
61 | VERIFIED[user.id] = str(today)
62 |
63 | async def check_verification(bot, userid):
64 | user = await bot.get_users(userid)
65 | tz = pytz.timezone('Asia/Kolkata')
66 | today = date.today()
67 | if user.id in VERIFIED.keys():
68 | EXP = VERIFIED[user.id]
69 | years, month, day = EXP.split('-')
70 | comp = date(int(years), int(month), int(day))
71 | if comp