Skip to content

Commit

Permalink
Torrent Auto-Detection and Further Improvements
Browse files Browse the repository at this point in the history
- Removed QB command; bot now auto-detects torrents and utilizes qbit engine.
- Resolved issue with bot PM check not functioning for admins.
- Implemented additional fixes and enhancements.
  • Loading branch information
5hojib authored Oct 8, 2023
1 parent 0ee0711 commit bcdb36f
Show file tree
Hide file tree
Showing 35 changed files with 294 additions and 351 deletions.
5 changes: 1 addition & 4 deletions bot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@

botStartTime = time()

basicConfig(format="[%(asctime)s] [%(levelname)s] - %(message)s",
datefmt="%d-%b-%y %I:%M:%S %p",
handlers=[FileHandler('log.txt'), StreamHandler()],
level=INFO)
basicConfig(format="[%(asctime)s] [%(levelname)s] - %(message)s - [%(filename)s, %(lineno)d]", datefmt="%d-%b-%y %I:%M:%S %p", handlers=[FileHandler('log.txt'), StreamHandler()], level=INFO)

LOGGER = getLogger(__name__)

Expand Down
39 changes: 18 additions & 21 deletions bot/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

from bot import bot, config_dict, user_data, botStartTime, LOGGER, Interval, DATABASE_URL, QbInterval, scheduler, bot_name
from .helper.ext_utils.fs_utils import start_cleanup, clean_all, exit_clean_up
from .helper.ext_utils.bot_utils import get_readable_file_size, get_readable_time, cmd_exec, sync_to_async, set_commands, update_user_ldata, new_thread, format_validity_time, new_task
from .helper.ext_utils.bot_utils import get_readable_file_size, get_readable_time, cmd_exec, sync_to_async, set_commands, update_user_ldata, new_thread, new_task
from .helper.ext_utils.db_handler import DbManager
from .helper.telegram_helper.bot_commands import BotCommands
from .helper.telegram_helper.message_utils import sendMessage, editMessage, sendFile, deleteMessage, one_minute_del, five_minute_del
Expand Down Expand Up @@ -106,7 +106,7 @@ async def start(client, message):
if DATABASE_URL:
await DbManager().update_user_tdata(userid, token, token_time)
msg = 'Your token has been successfully generated!\n\n'
msg += f'It will be valid for {format_validity_time(int(config_dict["TOKEN_TIMEOUT"]))}'
msg += f'It will be valid for {get_readable_time(int(config_dict["TOKEN_TIMEOUT"]), True)}'
return await sendMessage(message, msg)
elif await CustomFilters.authorized(client, message):
help_command = f"/{BotCommands.HelpCommand}"
Expand Down Expand Up @@ -204,27 +204,24 @@ async def log(_, message):
await five_minute_del(reply_message)


help_string = f'''
NOTE: Try each command without any arguments to see more details.
/{BotCommands.MirrorCommand[0]} or /{BotCommands.MirrorCommand[1]}: Starts mirroring to Google Drive.
/{BotCommands.QbMirrorCommand[0]} or /{BotCommands.QbMirrorCommand[1]}: Starts mirroring to Google Drive using qBittorrent.
/{BotCommands.YtdlCommand[0]} or /{BotCommands.YtdlCommand[1]}: Mirrors links supported by yt-dlp.
/{BotCommands.LeechCommand[0]} or /{BotCommands.LeechCommand[1]}: Starts leeching to Telegram.
/{BotCommands.QbLeechCommand[0]} or /{BotCommands.QbLeechCommand[1]}: Starts leeching using qBittorrent.
/{BotCommands.YtdlLeechCommand[0]} or /{BotCommands.YtdlLeechCommand[1]}: Leeches links supported by yt-dlp.
/{BotCommands.CloneCommand} [drive_url]: Copies files/folders to Google Drive.
/{BotCommands.CountCommand} [drive_url]: Counts files/folders in Google Drive.
/{BotCommands.DeleteCommand} [drive_url]: Deletes files/folders from Google Drive (Only Owner & Sudo).
/{BotCommands.UserSetCommand} [query]: User settings.
/{BotCommands.BotSetCommand} [query]: Bot settings.
/{BotCommands.BtSelectCommand}: Select files from torrents by gid or reply.
/{BotCommands.StopAllCommand} [query]: Cancel all [status] tasks.
/{BotCommands.ListCommand} [query]: Searches in Google Drive(s).
/{BotCommands.SearchCommand} [query]: Searches for torrents with API or plugins.
/{BotCommands.StatusCommand}: Shows status of all downloads.
/{BotCommands.StatsCommand}: Shows stats of the machine hosting the bot.
help_string = f'''<b>NOTE: Try each command without any arguments to see more details.</b>
/{BotCommands.MirrorCommand[0]} - Start mirroring to Google Drive.
/{BotCommands.LeechCommand[0]} - Start leeching to Telegram.
/{BotCommands.YtdlCommand[0]} - Mirror links supported by yt-dlp.
/{BotCommands.YtdlLeechCommand[0]} - Leech links supported by yt-dlp.
/{BotCommands.CloneCommand} - Copy files/folders to Google Drive.
/{BotCommands.CountCommand} - Count files/folders in Google Drive.
/{BotCommands.UserSetCommand[0]} - User settings.
/{BotCommands.BtSelectCommand} - Select files from torrents by gid or reply.
/{BotCommands.StopAllCommand[0]} - Cancel all [status] tasks.
/{BotCommands.ListCommand} - Search in Google Drive(s).
/{BotCommands.SearchCommand} - Search for torrents with API or plugins.
/{BotCommands.StatusCommand[0]} - Show status of all downloads.
/{BotCommands.StatsCommand[0]} - Show stats of the machine hosting the bot.
'''


@new_task
async def bot_help(client, message):
reply_message = await sendMessage(message, help_string)
Expand Down
4 changes: 2 additions & 2 deletions bot/helper/ext_utils/aeon_utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import pyshorteners
from pyshorteners import Shortener
from bot import LOGGER
from re import IGNORECASE, search, escape

Expand Down Expand Up @@ -49,7 +49,7 @@ async def nsfw_precheck(message):


def tinyfy(long_url):
s = pyshorteners.Shortener()
s = Shortener()
try:
short_url = s.tinyurl.short(long_url)
LOGGER.info(f'tinyfied {long_url} to {short_url}')
Expand Down
83 changes: 34 additions & 49 deletions bot/helper/ext_utils/bot_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from bot.helper.telegram_helper.bot_commands import BotCommands
from bot.helper.telegram_helper.button_build import ButtonMaker
from bot.helper.ext_utils.telegraph_helper import telegraph
from bot.helper.ext_utils.shortners import short_url
from bot.helper.ext_utils.shorteners import short_url
from bot.helper.ext_utils.aeon_utils import tinyfy

THREADPOOL = ThreadPoolExecutor(max_workers = 1000)
Expand Down Expand Up @@ -200,11 +200,11 @@ def get_readable_message():
for download in download_dict.values():
tstatus = download.status()
if tstatus == MirrorStatus.STATUS_DOWNLOADING:
dl_speed += text_size_to_bytes(download.speed())
dl_speed += text_to_bytes(download.speed())
elif tstatus == MirrorStatus.STATUS_UPLOADING:
up_speed += text_size_to_bytes(download.speed())
up_speed += text_to_bytes(download.speed())
elif tstatus == MirrorStatus.STATUS_SEEDING:
up_speed += text_size_to_bytes(download.upload_speed())
up_speed += text_to_bytes(download.upload_speed())
if tasks > STATUS_LIMIT:
buttons = ButtonMaker()
buttons.ibutton("Prev", "status pre")
Expand All @@ -219,18 +219,14 @@ def get_readable_message():
return msg, button


def text_size_to_bytes(size_text):
size = 0
def text_to_bytes(size_text):
size_text = size_text.lower()
if 'k' in size_text:
size += float(size_text.split('k')[0]) * 1024
elif 'm' in size_text:
size += float(size_text.split('m')[0]) * 1048576
elif 'g' in size_text:
size += float(size_text.split('g')[0]) * 1073741824
elif 't' in size_text:
size += float(size_text.split('t')[0]) * 1099511627776
return size
multiplier = {'k': 1024, 'm': 1048576, 'g': 1073741824, 't': 1099511627776, 'p': 1125899906842624}
for unit, factor in multiplier.items():
if unit in size_text:
size_value = float(size_text.split(unit)[0])
return size_value * factor
return 0


async def turn_page(data):
Expand All @@ -252,15 +248,15 @@ async def turn_page(data):
PAGE_NO -= 1


def get_readable_time(seconds):
def get_readable_time(seconds, full_time=False):
periods = [('millennium', 31536000000), ('century', 3153600000), ('decade', 315360000), ('year', 31536000), ('month', 2592000), ('week', 604800), ('day', 86400), ('hour', 3600), ('minute', 60), ('second', 1)]
result = ''
for period_name, period_seconds in periods:
if seconds >= period_seconds:
period_value, seconds = divmod(seconds, period_seconds)
plural_suffix = 's' if period_value > 1 else ''
result += f'{int(period_value)} {period_name}{plural_suffix} '
if len(result.split()) == 2:
if not full_time:
break
return result.strip()

Expand Down Expand Up @@ -429,25 +425,14 @@ async def checking_access(user_id, button=None):
if DATABASE_URL:
await DbManager().update_user_token(user_id, token)
user_data[user_id].update(data)
time_str = format_validity_time(token_timeout)
time_str = get_readable_time(token_timeout, True)
if button is None:
button = ButtonMaker()
button.ubutton('Collect token', tinyfy(short_url(f'https://telegram.me/{bot_name}?start={token}')))
return f'Your token has expired, please collect a new token.\n<b>It will expire after {time_str}</b>!', button
return None, button


def format_validity_time(seconds):
periods = [('millennium', 31536000000), ('century', 3153600000), ('decade', 315360000), ('year', 31536000), ('month', 2592000), ('week', 604800), ('day', 86400), ('hour', 3600), ('minute', 60), ('second', 1)]
result = ''
for period_name, period_seconds in periods:
if seconds >= period_seconds:
period_value, seconds = divmod(seconds, period_seconds)
plural_suffix = 's' if period_value > 1 else ''
result += f'{int(period_value)} {period_name}{plural_suffix} '
return result


def extra_btns(buttons):
if extra_buttons:
for btn_name, btn_url in extra_buttons.items():
Expand All @@ -457,23 +442,23 @@ def extra_btns(buttons):

async def set_commands(client):
if config_dict['SET_COMMANDS']:
await client.set_bot_commands(
[BotCommand(f'{BotCommands.MirrorCommand[0]}', f'or /{BotCommands.MirrorCommand[1]} Mirror'),
BotCommand(f'{BotCommands.LeechCommand[0]}', f'or /{BotCommands.LeechCommand[1]} Leech'),
BotCommand(f'{BotCommands.QbMirrorCommand[0]}', f'or /{BotCommands.QbMirrorCommand[1]} Mirror torrent using qBittorrent'),
BotCommand(f'{BotCommands.QbLeechCommand[0]}', f'or /{BotCommands.QbLeechCommand[1]} Leech torrent using qBittorrent'),
BotCommand(f'{BotCommands.YtdlCommand[0]}', f'or /{BotCommands.YtdlCommand[1]} Mirror yt-dlp supported link'),
BotCommand(f'{BotCommands.YtdlLeechCommand[0]}', f'or /{BotCommands.YtdlLeechCommand[1]} Leech through yt-dlp supported link'),
BotCommand(f'{BotCommands.CloneCommand}', 'Copy file/folder to Drive'),
BotCommand(f'{BotCommands.StatusCommand[0]}', f'or /{BotCommands.StatusCommand[1]} Get mirror status message'),
BotCommand(f'{BotCommands.StatsCommand[0]}', 'Check Bot & System stats'),
BotCommand(f'{BotCommands.StopAllCommand[0]}', 'Cancel all tasks which added by you to in bots.'),
BotCommand(f'{BotCommands.ListCommand}', 'Search in Drive'),
BotCommand(f'{BotCommands.SearchCommand}', 'Search in Torrent'),
BotCommand(f'{BotCommands.UserSetCommand[0]}', 'Users settings'),
BotCommand(f'{BotCommands.HelpCommand}', 'Get detailed help'),
BotCommand(f'{BotCommands.BotSetCommand}', 'Open Bot settings'),
BotCommand(f'{BotCommands.LogCommand}', 'View log'),
BotCommand(f'{BotCommands.MediaInfoCommand}', 'Get MediaInfo'),
BotCommand(f'{BotCommands.CountCommand}', 'Count file/folder of Google Drive.'),
BotCommand(f'{BotCommands.RestartCommand[0]}', 'Restart bot')])
commands = [
BotCommand(f'{BotCommands.MirrorCommand[0]}', '- Start mirroring'),
BotCommand(f'{BotCommands.LeechCommand[0]}', '- Start leeching'),
BotCommand(f'{BotCommands.YtdlCommand[0]}', '- Mirror yt-dlp supported link'),
BotCommand(f'{BotCommands.YtdlLeechCommand[0]}', '- Leech through yt-dlp supported link'),
BotCommand(f'{BotCommands.CloneCommand[0]}', '- Copy file/folder to Drive'),
BotCommand(f'{BotCommands.CountCommand}', '- Count file/folder on Google Drive.'),
BotCommand(f'{BotCommands.MediaInfoCommand}', '- Get MediaInfo'),
BotCommand(f'{BotCommands.ListCommand}', '- Search in Drive'),
BotCommand(f'{BotCommands.SearchCommand}', '- Search in Torrent'),
BotCommand(f'{BotCommands.UserSetCommand[0]}', '- User settings'),
BotCommand(f'{BotCommands.StatusCommand[0]}', '- Get mirror status message'),
BotCommand(f'{BotCommands.StatsCommand[0]}', '- Check Bot & System stats'),
BotCommand(f'{BotCommands.StopAllCommand[0]}', '- Cancel all tasks added by you to the bot.'),
BotCommand(f'{BotCommands.HelpCommand}', '- Get detailed help'),
BotCommand(f'{BotCommands.BotSetCommand}', '- Open Bot settings'),
BotCommand(f'{BotCommands.LogCommand}', '- View log'),
BotCommand(f'{BotCommands.RestartCommand[0]}', '- Restart the bot')
]
await client.set_bot_commands(commands)
36 changes: 1 addition & 35 deletions bot/helper/ext_utils/db_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,6 @@ async def update_aria2(self, key, value):
await self.__db.settings.aria2c.update_one({'_id': bot_id}, {'$set': {key: value}}, upsert=True)
self.__conn.close

async def update_qbittorrent(self, key, value):
if self.__err:
return
await self.__db.settings.qbittorrent.update_one({'_id': bot_id}, {'$set': {key: value}}, upsert=True)
self.__conn.close

async def update_private_file(self, path):
if self.__err:
return
Expand Down Expand Up @@ -163,34 +157,6 @@ async def trunc_table(self, name):
await self.__db[name][bot_id].drop()
self.__conn.close

async def add_download_url(self, url: str, tag: str):
if self.__err:
return
download = {'_id': url, 'tag': tag, 'botname': bot_name}
await self.__db.download_links.update_one({'_id': url}, {'$set': download}, upsert=True)
self.__conn.close

async def check_download(self, url: str):
if self.__err:
return
exist = await self.__db.download_links.find_one({'_id': url})
self.__conn.close
return exist

async def clear_download_links(self, botName=None):
if self.__err:
return
if not botName:
botName = bot_name
await self.__db.download_links.delete_many({'botname': botName})
self.__conn.close

async def remove_download(self, url: str):
if self.__err:
return
await self.__db.download_links.delete_one({'_id': url})
self.__conn.close

async def update_user_tdata(self, user_id, token, time):
if self.__err:
return
Expand Down Expand Up @@ -228,4 +194,4 @@ async def delete_all_access_tokens(self):
self.__conn.close

if DATABASE_URL:
bot_loop.run_until_complete(DbManager().db_load())
bot_loop.run_until_complete(DbManager().db_load())
2 changes: 1 addition & 1 deletion bot/helper/ext_utils/leech_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ def lowerVars(match):
cap_mono = slit[0].format(
filename = nfile_,
size = get_readable_file_size(await aiopath.getsize(up_path)),
duration = get_readable_time(dur),
duration = get_readable_time(dur, True),
quality = qual,
languages = lang,
subtitles = subs,
Expand Down
File renamed without changes.
13 changes: 5 additions & 8 deletions bot/helper/ext_utils/task_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ async def start_from_queued():
start_dl_from_queued(uid)


async def limit_checker(size, listener, isTorrent=False, isMega=False, isDriveLink=False, isYtdlp=False):
async def limit_checker(size, listener, isTorrent=False, isMega=False, isDriveLink=False, isYtdlp=False, isPlayList=None):
LOGGER.info('Checking limit')
user_id = listener.message.from_user.id
if user_id == OWNER_ID or user_id in user_data and user_data[user_id].get('is_sudo'):
Expand Down Expand Up @@ -170,26 +170,23 @@ async def limit_checker(size, listener, isTorrent=False, isMega=False, isDriveLi


async def task_utils(message):
LOGGER.info('Checking Task Utilities ...')
msg = []
button = None
user_id = message.from_user.id
token = config_dict['TOKEN_TIMEOUT']
admin = await isAdmin(message)
if message.chat.type != message.chat.type.BOT:
if ids := config_dict['FSUB_IDS']:
_msg, button = await forcesub(message, ids, button)
if _msg:
msg.append(_msg)
if not config_dict['TOKEN_TIMEOUT']:
_msg, button = await BotPm_check(message, button)
if _msg:
msg.append(_msg)
if config_dict['TOKEN_TIMEOUT'] and (await isAdmin(message) or user_id == OWNER_ID or user_id in user_data and user_data[user_id].get('is_sudo')):
if not token or (token and (admin or user_id == OWNER_ID or (user_id in user_data and user_data[user_id].get('is_sudo')))):
_msg, button = await BotPm_check(message, button)
if _msg:
msg.append(_msg)
if user_id == OWNER_ID or user_id in user_data and user_data[user_id].get('is_sudo'):
return msg, button
if await isAdmin(message):
if admin:
return msg, button
token_msg, button = await checking_access(message.from_user.id, button)
if token_msg is not None:
Expand Down
Loading

0 comments on commit bcdb36f

Please sign in to comment.