mirror of
https://github.com/avipatilpro/FileStreamBot.git
synced 2026-01-15 14:22:53 -03:00
Initial Commit
2.0
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,4 +1,4 @@
|
||||
# Byte-compiled / optimized / DLL file
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
@@ -114,4 +114,4 @@ dmypy.json
|
||||
.pyre/
|
||||
|
||||
#session files
|
||||
*.session
|
||||
*.session
|
||||
2
.replit
Normal file
2
.replit
Normal file
@@ -0,0 +1,2 @@
|
||||
language = "bash"
|
||||
run = "pip3 install -r requirements.txt; python3 -m WebStreamer"
|
||||
@@ -1,5 +1 @@
|
||||
|
||||
# Maintained By : Avishkar Patil [ @Avishkarpatil ] [ Telegram ]
|
||||
|
||||
import time
|
||||
StartTime = time.time()
|
||||
# This file is a part of avipatilpro/FileStreamBot
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
@@ -11,14 +12,6 @@ from .vars import Var
|
||||
from aiohttp import web
|
||||
from .server import web_server
|
||||
from .utils.keepalive import ping_server
|
||||
from apscheduler.schedulers.background import BackgroundScheduler
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
logging.getLogger("pyrogram").setLevel(logging.WARNING)
|
||||
logging.getLogger("apscheduler").setLevel(logging.WARNING)
|
||||
|
||||
ppath = "WebStreamer/bot/plugins/*.py"
|
||||
files = glob.glob(ppath)
|
||||
@@ -30,9 +23,10 @@ async def start_services():
|
||||
print('\n')
|
||||
print('------------------- Initalizing Telegram Bot -------------------')
|
||||
await StreamBot.start()
|
||||
print('----------------------------- DONE -----------------------------')
|
||||
print('\n')
|
||||
print('--------------------------- Importing ---------------------------')
|
||||
print('---------------------- DONE ----------------------')
|
||||
print('\n')
|
||||
print('------------------- Importing -------------------')
|
||||
for name in files:
|
||||
with open(name) as a:
|
||||
patt = Path(a.name)
|
||||
@@ -44,24 +38,22 @@ async def start_services():
|
||||
spec.loader.exec_module(load)
|
||||
sys.modules["WebStreamer.bot.plugins." + plugin_name] = load
|
||||
print("Imported => " + plugin_name)
|
||||
if Var.ON_HEROKU:
|
||||
print('------------------ Starting Keep Alive Service ------------------')
|
||||
print('\n')
|
||||
scheduler = BackgroundScheduler()
|
||||
scheduler.add_job(ping_server, "interval", seconds=1200)
|
||||
scheduler.start()
|
||||
print('-------------------- Initalizing Web Server --------------------')
|
||||
print('\n')
|
||||
print('------------------- Initalizing Web Server -------------------')
|
||||
app = web.AppRunner(await web_server())
|
||||
await app.setup()
|
||||
bind_address = "0.0.0.0" if Var.ON_HEROKU else Var.FQDN
|
||||
await web.TCPSite(app, bind_address, Var.PORT).start()
|
||||
print('----------------------------- DONE -----------------------------')
|
||||
print('\n')
|
||||
print('----------------------- Service Started -----------------------')
|
||||
print(' bot =>> {}'.format((await StreamBot.get_me()).first_name))
|
||||
print(' server ip =>> {}:{}'.format(bind_address, Var.PORT))
|
||||
if Var.ON_HEROKU:
|
||||
print(' app runnng on =>> {}'.format(Var.FQDN))
|
||||
if Var.ON_HEROKU:
|
||||
print('------------------ Starting Keep Alive Service ------------------')
|
||||
print('\n')
|
||||
await asyncio.create_task(ping_server())
|
||||
print('---------------------------------------------------------------')
|
||||
await idle()
|
||||
|
||||
@@ -69,4 +61,4 @@ if __name__ == '__main__':
|
||||
try:
|
||||
loop.run_until_complete(start_services())
|
||||
except KeyboardInterrupt:
|
||||
logging.info('----------------------- Service Stopped -----------------------')
|
||||
print('----------------------- Service Stopped -----------------------')
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# This file is a part of TG-FileStreamBot
|
||||
# Coding : Jyothis Jayanth [@EverythingSuckz]
|
||||
|
||||
from pyrogram import Client
|
||||
from ..vars import Var
|
||||
@@ -11,4 +9,4 @@ StreamBot = Client(
|
||||
bot_token=Var.BOT_TOKEN,
|
||||
sleep_threshold=Var.SLEEP_THRESHOLD,
|
||||
workers=Var.WORKERS
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# (c) @Avishkarpatil | @AbirHasan2005
|
||||
# (c) @Avishkarpatil
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# © @AvishkarPatil [ Telegram ]
|
||||
|
||||
import urllib.parse
|
||||
from WebStreamer.bot import StreamBot
|
||||
from WebStreamer.vars import Var
|
||||
from WebStreamer.utils.human_readable import humanbytes
|
||||
@@ -7,6 +6,7 @@ from WebStreamer.utils.database import Database
|
||||
from pyrogram import filters
|
||||
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||
from pyrogram.errors import UserNotParticipant
|
||||
|
||||
db = Database(Var.DATABASE_URL, Var.SESSION_NAME)
|
||||
|
||||
START_TEXT = """
|
||||
@@ -79,6 +79,21 @@ async def cb_data(bot, update):
|
||||
else:
|
||||
await update.message.delete()
|
||||
|
||||
def get_media_file_size(m):
|
||||
media = m.video or m.audio or m.document
|
||||
if media and media.file_size:
|
||||
return media.file_size
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def get_media_file_name(m):
|
||||
media = m.video or m.document or m.audio
|
||||
if media and media.file_name:
|
||||
return urllib.parse.quote_plus(media.file_name)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
@StreamBot.on_message(filters.command('start') & filters.private & ~filters.edited)
|
||||
async def start(b, m):
|
||||
@@ -146,8 +161,10 @@ async def start(b, m):
|
||||
text="**Pʟᴇᴀsᴇ Jᴏɪɴ Mʏ Uᴘᴅᴀᴛᴇs Cʜᴀɴɴᴇʟ ᴛᴏ ᴜsᴇ ᴛʜɪs Bᴏᴛ**!\n\n**Dᴜᴇ ᴛᴏ Oᴠᴇʀʟᴏᴀᴅ, Oɴʟʏ Cʜᴀɴɴᴇʟ Sᴜʙsᴄʀɪʙᴇʀs ᴄᴀɴ ᴜsᴇ ᴛʜᴇ Bᴏᴛ**!",
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[[
|
||||
InlineKeyboardButton("🤖 Jᴏɪɴ Uᴘᴅᴀᴛᴇs Cʜᴀɴɴᴇʟ", url=f"https://t.me/{Var.UPDATES_CHANNEL}")
|
||||
]]
|
||||
InlineKeyboardButton("🤖 Jᴏɪɴ Uᴘᴅᴀᴛᴇs Cʜᴀɴɴᴇʟ", url=f"https://t.me/{Var.UPDATES_CHANNEL}")],
|
||||
[InlineKeyboardButton("🔄 Refresh / Try Again", url=f"https://t.me/{(await b.get_me()).username}?start=AvishkarPatil_{usr_cmd}")
|
||||
|
||||
]]
|
||||
),
|
||||
parse_mode="markdown"
|
||||
)
|
||||
@@ -161,27 +178,14 @@ async def start(b, m):
|
||||
return
|
||||
|
||||
get_msg = await b.get_messages(chat_id=Var.BIN_CHANNEL, message_ids=int(usr_cmd))
|
||||
file_name = get_media_file_name(get_msg)
|
||||
file_size = humanbytes(get_media_file_size(get_msg))
|
||||
|
||||
file_size = None
|
||||
if get_msg.video:
|
||||
file_size = f"{humanbytes(get_msg.video.file_size)}"
|
||||
elif get_msg.document:
|
||||
file_size = f"{humanbytes(get_msg.document.file_size)}"
|
||||
elif get_msg.audio:
|
||||
file_size = f"{humanbytes(get_msg.audio.file_size)}"
|
||||
|
||||
file_name = None
|
||||
if get_msg.video:
|
||||
file_name = f"{get_msg.video.file_name}"
|
||||
elif get_msg.document:
|
||||
file_name = f"{get_msg.document.file_name}"
|
||||
elif get_msg.audio:
|
||||
file_name = f"{get_msg.audio.file_name}"
|
||||
|
||||
stream_link = "https://{}/{}".format(Var.FQDN, get_msg.message_id) if Var.ON_HEROKU or Var.NO_PORT else \
|
||||
"http://{}:{}/{}".format(Var.FQDN,
|
||||
stream_link = "https://{}/{}/{}".format(Var.FQDN, get_msg.message_id, file_name) if Var.ON_HEROKU or Var.NO_PORT else \
|
||||
"http://{}:{}/{}/{}".format(Var.FQDN,
|
||||
Var.PORT,
|
||||
get_msg.message_id)
|
||||
get_msg.message_id,
|
||||
file_name)
|
||||
|
||||
msg_text ="""
|
||||
<i><u>𝗬𝗼𝘂𝗿 𝗟𝗶𝗻𝗸 𝗚𝗲𝗻𝗲𝗿𝗮𝘁𝗲𝗱 !</u></i>\n
|
||||
@@ -199,6 +203,7 @@ async def start(b, m):
|
||||
)
|
||||
|
||||
|
||||
|
||||
@StreamBot.on_message(filters.private & filters.command(["about"]))
|
||||
async def start(bot, update):
|
||||
await update.reply_text(
|
||||
@@ -252,3 +257,4 @@ async def help_handler(bot, message):
|
||||
disable_web_page_preview=True,
|
||||
reply_markup=HELP_BUTTONS
|
||||
)
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
|
||||
# (c) @Avishkarpatil
|
||||
|
||||
|
||||
import asyncio
|
||||
import urllib.parse
|
||||
from WebStreamer.bot import StreamBot
|
||||
from WebStreamer.utils.database import Database
|
||||
from WebStreamer.utils.human_readable import humanbytes
|
||||
@@ -12,6 +14,22 @@ from pyrogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton
|
||||
db = Database(Var.DATABASE_URL, Var.SESSION_NAME)
|
||||
|
||||
|
||||
def get_media_file_size(m):
|
||||
media = m.video or m.audio or m.document
|
||||
if media and media.file_size:
|
||||
return media.file_size
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def get_media_file_name(m):
|
||||
media = m.video or m.document or m.audio
|
||||
if media and media.file_name:
|
||||
return urllib.parse.quote_plus(media.file_name)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
@StreamBot.on_message(filters.private & (filters.document | filters.video | filters.audio) & ~filters.edited, group=4)
|
||||
async def private_receive_handler(c: Client, m: Message):
|
||||
if not await db.is_user_exist(m.from_user.id):
|
||||
@@ -50,25 +68,13 @@ async def private_receive_handler(c: Client, m: Message):
|
||||
return
|
||||
try:
|
||||
log_msg = await m.forward(chat_id=Var.BIN_CHANNEL)
|
||||
stream_link = "https://{}/{}".format(Var.FQDN, log_msg.message_id) if Var.ON_HEROKU or Var.NO_PORT else \
|
||||
"http://{}:{}/{}".format(Var.FQDN,
|
||||
file_name = get_media_file_name(m)
|
||||
file_size = humanbytes(get_media_file_size(m))
|
||||
stream_link = "https://{}/{}/{}".format(Var.FQDN, log_msg.message_id, file_name) if Var.ON_HEROKU or Var.NO_PORT else \
|
||||
"http://{}:{}/{}/{}".format(Var.FQDN,
|
||||
Var.PORT,
|
||||
log_msg.message_id)
|
||||
file_size = None
|
||||
if m.video:
|
||||
file_size = f"{humanbytes(m.video.file_size)}"
|
||||
elif m.document:
|
||||
file_size = f"{humanbytes(m.document.file_size)}"
|
||||
elif m.audio:
|
||||
file_size = f"{humanbytes(m.audio.file_size)}"
|
||||
|
||||
file_name = None
|
||||
if m.video:
|
||||
file_name = f"{m.video.file_name}"
|
||||
elif m.document:
|
||||
file_name = f"{m.document.file_name}"
|
||||
elif m.audio:
|
||||
file_name = f"{m.audio.file_name}"
|
||||
log_msg.message_id,
|
||||
file_name)
|
||||
|
||||
msg_text ="""
|
||||
<i><u>𝗬𝗼𝘂𝗿 𝗟𝗶𝗻𝗸 𝗚𝗲𝗻𝗲𝗿𝗮𝘁𝗲𝗱 !</u></i>\n
|
||||
@@ -104,7 +110,7 @@ async def channel_receive_handler(bot, broadcast):
|
||||
Var.PORT,
|
||||
log_msg.message_id)
|
||||
await log_msg.reply_text(
|
||||
text=f"**Cʜᴀɴɴᴇʟ Nᴀᴍᴇ:** `{broadcast.chat.title}`\n**Cʜᴀɴɴᴇʟ ID:** `{broadcast.chat.id}`\n**Rᴇǫᴜᴇsᴛ ᴜʀʟ:** {stream_link}",
|
||||
text=f"**Cʜᴀɴɴᴇʟ Nᴀᴍᴇ:** `{broadcast.chat.title}`\n**Cʜᴀɴɴᴇʟ ID:** `{broadcast.chat.id}`\n**Rᴇǫᴜᴇsᴛ ᴜʀʟ:** https://t.me/{(await bot.get_me()).username}?start=AvishkarPatil_{str(log_msg.message_id)}",
|
||||
# text=f"**Cʜᴀɴɴᴇʟ Nᴀᴍᴇ:** `{broadcast.chat.title}`\n**Cʜᴀɴɴᴇʟ ID:** `{broadcast.chat.id}`\n**Rᴇǫᴜᴇsᴛ ᴜʀʟ:** https://t.me/FxStreamBot?start=AvishkarPatil_{str(log_msg.message_id)}",
|
||||
quote=True,
|
||||
parse_mode="Markdown"
|
||||
@@ -113,7 +119,7 @@ async def channel_receive_handler(bot, broadcast):
|
||||
chat_id=broadcast.chat.id,
|
||||
message_id=broadcast.message_id,
|
||||
reply_markup=InlineKeyboardMarkup(
|
||||
[[InlineKeyboardButton("Dᴏᴡɴʟᴏᴀᴅ ʟɪɴᴋ 📥", url=stream_link)]])
|
||||
[[InlineKeyboardButton("Dᴏᴡɴʟᴏᴀᴅ ʟɪɴᴋ 📥", url=f"https://t.me/{(await bot.get_me()).username}?start=AvishkarPatil_{str(log_msg.message_id)}")]])
|
||||
# [[InlineKeyboardButton("Dᴏᴡɴʟᴏᴀᴅ ʟɪɴᴋ 📥", url=f"https://t.me/FxStreamBot?start=AvishkarPatil_{str(log_msg.message_id)}")]])
|
||||
)
|
||||
except FloodWait as w:
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# © Avishkar Patil [ @AvishkarPatil ] [ Telegram ]
|
||||
# Coding : Jyothis Jayanth [@EverythingSuckz]
|
||||
|
||||
from aiohttp import web
|
||||
from .stream_routes import routes
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import time
|
||||
# Avishkar Patil | AbirHasan2005
|
||||
|
||||
import math
|
||||
import logging
|
||||
import secrets
|
||||
@@ -6,21 +7,23 @@ import mimetypes
|
||||
from ..vars import Var
|
||||
from aiohttp import web
|
||||
from ..bot import StreamBot
|
||||
from WebStreamer import StartTime
|
||||
from ..utils.custom_dl import TGCustomYield, chunk_size, offset_fix
|
||||
from ..utils.time_format import get_readable_time
|
||||
|
||||
routes = web.RouteTableDef()
|
||||
|
||||
|
||||
@routes.get("/", allow_head=True)
|
||||
async def root_route_handler(request):
|
||||
bot_details = await StreamBot.get_me()
|
||||
return web.json_response({"status": "running",
|
||||
"maintained_by": "Avishkar_Patil",
|
||||
"uptime": get_readable_time(time.time() - StartTime),
|
||||
"telegram_bot": '@'+(await StreamBot.get_me()).username})
|
||||
"server_permission": "Open",
|
||||
"Telegram_Bot": '@'+bot_details.username})
|
||||
|
||||
|
||||
@routes.get("/{message_id}")
|
||||
@routes.get("/{message_id}/")
|
||||
@routes.get(r"/{message_id:\d+}/{name}")
|
||||
async def stream_handler(request):
|
||||
try:
|
||||
message_id = int(request.match_info['message_id'])
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
# This file is a part of TG-FileStreamBot
|
||||
# Coding : Jyothis Jayanth [@EverythingSuckz]
|
||||
# Maintained By : Avishkar Patil [ @AvishkarPatil ] [ Telegram ]
|
||||
# This file is a part of avipatilpro/FileStreamBot
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# (c) @AbirHasan2005
|
||||
|
||||
import asyncio
|
||||
import traceback
|
||||
@@ -19,4 +18,4 @@ async def send_msg(user_id, message):
|
||||
except PeerIdInvalid:
|
||||
return 400, f"{user_id} : user id invalid\n"
|
||||
except Exception as e:
|
||||
return 500, f"{user_id} : {traceback.format_exc()}\n"
|
||||
return 500, f"{user_id} : {traceback.format_exc()}\n"
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# Taken from megadlbot_oss <https://github.com/eyaadh/megadlbot_oss/blob/master/mega/telegram/utils/custom_download.py>
|
||||
# Thanks to Eyaadh <https://github.com/eyaadh>
|
||||
|
||||
import math
|
||||
from typing import Union
|
||||
@@ -230,4 +228,4 @@ class TGCustomYield:
|
||||
)
|
||||
)
|
||||
|
||||
return m_file
|
||||
return m_file
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# (c) @AbirHasan2005
|
||||
|
||||
|
||||
import datetime
|
||||
import motor.motor_asyncio
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# (c) @AbirHasan2005
|
||||
|
||||
|
||||
def humanbytes(size):
|
||||
# https://stackoverflow.com/a/49361727/4723940
|
||||
@@ -12,4 +10,4 @@ def humanbytes(size):
|
||||
while size > power:
|
||||
size /= power
|
||||
n += 1
|
||||
return str(round(size, 2)) + " " + Dic_powerN[n] + 'B'
|
||||
return str(round(size, 2)) + " " + Dic_powerN[n] + 'B'
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
# Bot Sleeping
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import requests
|
||||
from ..vars import Var
|
||||
def ping_server():
|
||||
k = requests.get(f'https://ping-pong-sn.herokuapp.com/pingback?link={Var.URL}').json()
|
||||
if not k.get('error'):
|
||||
logging.info('KeepAliveService: Pinged {} with status {}'.format(Var.FQDN, k.get('Status')))
|
||||
else:
|
||||
logging.error('Couldn\'t Ping the Server!')
|
||||
import aiohttp
|
||||
import traceback
|
||||
from WebStreamer.vars import Var
|
||||
|
||||
URL = f"https://{Var.FQDN}"
|
||||
|
||||
|
||||
async def ping_server():
|
||||
sleep_time = Var.PING_INTERVAL
|
||||
while True:
|
||||
await asyncio.sleep(sleep_time)
|
||||
try:
|
||||
async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=10)) as session:
|
||||
async with session.get(Var.URL) as resp:
|
||||
logging.info("Pinged server with response: {}".format(resp.status))
|
||||
except TimeoutError:
|
||||
logging.warning("Couldn't connect to the site URL..!")
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
# Bot Uptime
|
||||
|
||||
def get_readable_time(seconds: int) -> str:
|
||||
count = 0
|
||||
readable_time = ""
|
||||
time_list = []
|
||||
time_suffix_list = ["s", "m", "h", " days"]
|
||||
while count < 4:
|
||||
count += 1
|
||||
if count < 3:
|
||||
remainder, result = divmod(seconds, 60)
|
||||
else:
|
||||
remainder, result = divmod(seconds, 24)
|
||||
if seconds == 0 and remainder == 0:
|
||||
break
|
||||
time_list.append(int(result))
|
||||
seconds = int(remainder)
|
||||
for x in range(len(time_list)):
|
||||
time_list[x] = str(time_list[x]) + time_suffix_list[x]
|
||||
if len(time_list) == 4:
|
||||
readable_time += time_list.pop() + ", "
|
||||
time_list.reverse()
|
||||
readable_time += ": ".join(time_list)
|
||||
return readable_time
|
||||
@@ -10,13 +10,13 @@ class Var(object):
|
||||
API_ID = int(getenv('API_ID'))
|
||||
API_HASH = str(getenv('API_HASH'))
|
||||
BOT_TOKEN = str(getenv('BOT_TOKEN'))
|
||||
SESSION_NAME = str(getenv('SESSION_NAME', 'F2LxBot'))
|
||||
SESSION_NAME = str(getenv('SESSION_NAME', 'AviStreamBot'))
|
||||
SLEEP_THRESHOLD = int(getenv('SLEEP_THRESHOLD', '60'))
|
||||
WORKERS = int(getenv('WORKERS', '4'))
|
||||
BIN_CHANNEL = int(getenv('BIN_CHANNEL'))
|
||||
PORT = int(getenv('PORT', 8080))
|
||||
BIND_ADRESS = str(getenv('WEB_SERVER_BIND_ADDRESS', '0.0.0.0'))
|
||||
OWNER_ID = int(getenv('OWNER_ID', '1445283714'))
|
||||
OWNER_ID = int(getenv('OWNER_ID', '797848243'))
|
||||
NO_PORT = bool(getenv('NO_PORT', False))
|
||||
APP_NAME = None
|
||||
if 'DYNO' in environ:
|
||||
@@ -29,4 +29,4 @@ class Var(object):
|
||||
"http://{}:{}/".format(FQDN, PORT)
|
||||
DATABASE_URL = str(getenv('DATABASE_URL'))
|
||||
UPDATES_CHANNEL = str(getenv('UPDATES_CHANNEL', None))
|
||||
BANNED_CHANNELS = list(set(int(x) for x in str(getenv("BANNED_CHANNELS", "-1001362659779")).split()))
|
||||
BANNED_CHANNELS = list(set(int(x) for x in str(getenv("BANNED_CHANNELS", "-1001296894100")).split()))
|
||||
2
app.json
2
app.json
@@ -15,7 +15,7 @@
|
||||
"repository": "https://github.com/avipatilpro/FileStreamBot/",
|
||||
"success_url": "/",
|
||||
"logo": "https://i.ibb.co/ZJzJ9Hq/link-3x.png",
|
||||
"website": "avipatilweb.me",
|
||||
"website": "avipatilweb.ml",
|
||||
"env": {
|
||||
"ENV": {
|
||||
"description": "Set this to True if you don't want to crash the bot",
|
||||
|
||||
@@ -4,6 +4,4 @@ aiohttp
|
||||
python-dotenv
|
||||
motor
|
||||
aiofiles
|
||||
dnspython
|
||||
apscheduler
|
||||
requests
|
||||
dnspython
|
||||
Reference in New Issue
Block a user