From 35ad3e524e5e7eb4971cc4df5e697b9e4ad95cd8 Mon Sep 17 00:00:00 2001 From: Hafitz Setya <71178188+breakdowns@users.noreply.github.com> Date: Wed, 3 Mar 2021 09:12:39 +0700 Subject: [PATCH] v2.5 (#10) - /list command now results will be uploaded to telegra.ph - Auto generate Telegraph Token - Added Inline Buttons - Update /stats command --- bot/__init__.py | 7 ++ bot/__main__.py | 24 ++-- .../mirror_utils/upload_utils/gdriveTools.py | 113 ++++++++++++++---- bot/helper/telegram_helper/button_build.py | 16 +++ bot/helper/telegram_helper/message_utils.py | 10 +- bot/modules/clone.py | 4 +- bot/modules/list.py | 27 +++-- bot/modules/mirror.py | 12 +- requirements.txt | 2 + 9 files changed, 159 insertions(+), 56 deletions(-) create mode 100644 bot/helper/telegram_helper/button_build.py diff --git a/bot/__init__.py b/bot/__init__.py index e858f36ada1..ab6eed4af2e 100644 --- a/bot/__init__.py +++ b/bot/__init__.py @@ -6,6 +6,7 @@ import telegram.ext as tg from dotenv import load_dotenv from pyrogram import Client +from telegraph import Telegraph import socket socket.setdefaulttimeout(600) @@ -105,6 +106,12 @@ def getConfig(name: str): LOGGER.info("Generating USER_SESSION_STRING") with Client(':memory:', api_id=int(TELEGRAM_API), api_hash=TELEGRAM_HASH, bot_token=BOT_TOKEN) as app: USER_SESSION_STRING = app.export_session_string() +#Generate Telegraph Token +LOGGER.info("Generating Telegraph Token") +telegraph = Telegraph() +telegraph.create_account(short_name="mirror_bot") +telegraph_token = telegraph.get_access_token() + try: INDEX_URL = getConfig('INDEX_URL') if len(INDEX_URL) == 0: diff --git a/bot/__main__.py b/bot/__main__.py index 854d4de12ed..8ab2397f6b5 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -24,14 +24,20 @@ def stats(update, context): total = get_readable_file_size(total) used = get_readable_file_size(used) free = get_readable_file_size(free) + sent = get_readable_file_size(psutil.net_io_counters().bytes_sent) + recv = get_readable_file_size(psutil.net_io_counters().bytes_recv) cpuUsage = psutil.cpu_percent(interval=0.5) memory = psutil.virtual_memory().percent - stats = f'Bot Uptime: {currentTime}\n' \ - f'Total disk space: {total}\n' \ - f'Used: {used}\n' \ - f'Free: {free}\n' \ - f'CPU: {cpuUsage}%\n' \ - f'RAM: {memory}%' + disk = psutil.disk_usage('/').percent + stats = f'Bot Uptime: {currentTime}\n' \ + f'Total disk space: {total}\n' \ + f'Used: {used} ' \ + f'Free: {free}\n\n' \ + f'📊Data Usage📊\nUpload: {sent}\n' \ + f'Down: {recv}\n\n' \ + f'CPU: {cpuUsage}%\n' \ + f'RAM: {memory}%\n' \ + f'Disk: {disk}%' sendMessage(stats, context.bot, update) @@ -74,9 +80,11 @@ def bot_help(update, context): /{BotCommands.MirrorCommand} [download_url][magnet_link]: Start mirroring the link to google drive -/{BotCommands.UnzipMirrorCommand} [download_url][magnet_link]: starts mirroring and if downloaded file is any archive, extracts it to google drive +/{BotCommands.UnzipMirrorCommand} [download_url][magnet_link]: Starts mirroring and if downloaded file is any archive, extracts it to google drive -/{BotCommands.TarMirrorCommand} [download_url][magnet_link]: start mirroring and upload the archived (.tar) version of the download +/{BotCommands.CloneCommand}: Copy file/folder to google drive + +/{BotCommands.TarMirrorCommand} [download_url][magnet_link]: Start mirroring and upload the archived (.tar) version of the download /{BotCommands.WatchCommand} [youtube-dl supported link]: Mirror through youtube-dl diff --git a/bot/helper/mirror_utils/upload_utils/gdriveTools.py b/bot/helper/mirror_utils/upload_utils/gdriveTools.py index 27c20d8eae6..391325ae20d 100644 --- a/bot/helper/mirror_utils/upload_utils/gdriveTools.py +++ b/bot/helper/mirror_utils/upload_utils/gdriveTools.py @@ -16,15 +16,18 @@ from googleapiclient.http import MediaFileUpload from tenacity import * +from telegram import InlineKeyboardMarkup +from bot.helper.telegram_helper import button_build +from telegraph import Telegraph from bot import parent_id, DOWNLOAD_DIR, IS_TEAM_DRIVE, INDEX_URL, \ - USE_SERVICE_ACCOUNTS, download_dict + USE_SERVICE_ACCOUNTS, download_dict, telegraph_token from bot.helper.ext_utils.bot_utils import * from bot.helper.ext_utils.fs_utils import get_mime_type LOGGER = logging.getLogger(__name__) logging.getLogger('googleapiclient.discovery').setLevel(logging.ERROR) SERVICE_ACCOUNT_INDEX = 0 - +TELEGRAPHLIMIT = 95 class GoogleDriveHelper: def __init__(self, name=None, listener=None): @@ -51,6 +54,8 @@ def __init__(self, name=None, listener=None): self.updater = None self.name = name self.update_interval = 3 + self.telegraph_content = [] + self.path = [] def cancel(self): self.is_cancelled = True @@ -311,21 +316,24 @@ def clone(self, link): if meta.get("mimeType") == self.__G_DRIVE_DIR_MIME_TYPE: dir_id = self.create_directory(meta.get('name'), parent_id) result = self.cloneFolder(meta.get('name'), meta.get('name'), meta.get('id'), dir_id) - msg += f'{meta.get("name")}' \ - f' ({get_readable_file_size(self.transferred_size)})' + msg += f'Filename : {meta.get("name")}\nSize : {get_readable_file_size(self.transferred_size)}' + buttons = button_build.ButtonMaker() + buttons.buildbutton("✨Drive Link✨", self.__G_DRIVE_DIR_BASE_DOWNLOAD_URL.format(dir_id)) if INDEX_URL is not None: url = requests.utils.requote_uri(f'{INDEX_URL}/{meta.get("name")}/') - msg += f' | Index URL' + buttons.buildbutton("⚡Index Link⚡", url) else: file = self.copyFile(meta.get('id'), parent_id) - msg += f'{file.get("name")}' + msg += f'Filename : {file.get("name")}' + buttons = button_build.ButtonMaker() + buttons.buildbutton("✨Drive Link✨", self.__G_DRIVE_BASE_DOWNLOAD_URL.format(file.get("id"))) try: - msg += f' ({get_readable_file_size(int(meta.get("size")))}) ' + msg += f'\nSize : {get_readable_file_size(int(meta.get("size")))}' except TypeError: pass if INDEX_URL is not None: url = requests.utils.requote_uri(f'{INDEX_URL}/{file.get("name")}') - msg += f' | Index URL' + buttons.buildbutton("⚡Index Link⚡", url) except Exception as err: if isinstance(err, RetryError): LOGGER.info(f"Total Attempts: {err.last_attempt.attempt_number}") @@ -333,7 +341,7 @@ def clone(self, link): err = str(err).replace('>', '').replace('<', '') LOGGER.error(err) return err - return msg + return msg, InlineKeyboardMarkup(buttons.build_menu(2)) def cloneFolder(self, name, local_path, folder_id, parent_id): LOGGER.info(f"Syncing: {local_path}") @@ -424,6 +432,26 @@ def authorize(self): f'accounts/{SERVICE_ACCOUNT_INDEX}.json', scopes=self.__OAUTH_SCOPE) return build('drive', 'v3', credentials=credentials, cache_discovery=False) + def edit_telegraph(self): + nxt_page = 1 + prev_page = 0 + for content in self.telegraph_content : + if nxt_page == 1 : + content += f'Next' + nxt_page += 1 + else : + if prev_page <= self.num_of_path: + content += f'Prev' + prev_page += 1 + if nxt_page < self.num_of_path: + content += f' | Next' + nxt_page += 1 + Telegraph(access_token=telegraph_token).edit_page(path = self.path[prev_page], + title = 'Mirror Bot Search', + author_name='Mirror Bot', + author_url='https://github.com/magneto261290/magneto-python-ariap', + html_content=content) + return def escapes(self, str): chars = ['\\', "'", '"', r'\a', r'\b', r'\f', r'\n', r'\r', r'\t'] @@ -440,22 +468,55 @@ def drive_list(self, fileName): includeTeamDriveItems=True, q=query, spaces='drive', - pageSize=20, + pageSize=200, fields='files(id, name, mimeType, size)', orderBy='modifiedTime desc').execute() - for file in response.get('files', []): - if file.get( - 'mimeType') == "application/vnd.google-apps.folder": # Detect Whether Current Entity is a Folder or File. - msg += f"⁍ {file.get('name')}" \ - f" (folder)" - if INDEX_URL is not None: - url = requests.utils.requote_uri(f'{INDEX_URL}/{file.get("name")}/') - msg += f' | Index URL' - else: - msg += f"⁍ {file.get('name')} ({get_readable_file_size(int(file.get('size')))})" - if INDEX_URL is not None: - url = requests.utils.requote_uri(f'{INDEX_URL}/{file.get("name")}') - msg += f' | Index URL' - msg += '\n' - return msg + content_count = 0 + if response["files"]: + msg += f'

Results : {fileName}



' + for file in response.get('files', []): + if file.get('mimeType') == "application/vnd.google-apps.folder": # Detect Whether Current Entity is a Folder or File. + msg += f"⁍{file.get('name')}
(folder📁)

" \ + f"Drive Link" + if INDEX_URL is not None: + url = requests.utils.requote_uri(f'{INDEX_URL}/{file.get("name")}/') + msg += f' | Index Link' + else: + msg += f"⁍{file.get('name')}
({get_readable_file_size(int(file.get('size')))})📄

" \ + f"Drive Link" + if INDEX_URL is not None: + url = requests.utils.requote_uri(f'{INDEX_URL}/{file.get("name")}') + msg += f' | Index Link' + msg += '

' + content_count += 1 + if content_count == TELEGRAPHLIMIT : + self.telegraph_content.append(msg) + msg = "" + content_count = 0 + + if msg != '': + self.telegraph_content.append(msg) + + if len(self.telegraph_content) == 0: + return "No Result Found :(", None + + for content in self.telegraph_content : + self.path.append(Telegraph(access_token=telegraph_token).create_page( + title = 'Slam Mirror Bot Search', + author_name='Slam Mirror Bot', + author_url='https://github.com/breakdowns/slam-mirrorbot', + html_content=content + )['path']) + + self.num_of_path = len(self.path) + if self.num_of_path > 1: + self.edit_telegraph() + + msg = f"Search Results For {fileName} 👇" + buttons = button_build.ButtonMaker() + buttons.buildbutton("HERE", f"https://telegra.ph/{self.path[0]}") + + return msg, InlineKeyboardMarkup(buttons.build_menu(1)) + + else : + return '', '' diff --git a/bot/helper/telegram_helper/button_build.py b/bot/helper/telegram_helper/button_build.py new file mode 100644 index 00000000000..0d6726e1535 --- /dev/null +++ b/bot/helper/telegram_helper/button_build.py @@ -0,0 +1,16 @@ +from telegram import InlineKeyboardButton + +class ButtonMaker: + def __init__(self): + self.button = [] + + def buildbutton(self, key, link): + self.button.append(InlineKeyboardButton(text = key, url = link)) + + def build_menu(self, n_cols, footer_buttons=None, header_buttons=None): + menu = [self.button[i:i + n_cols] for i in range(0, len(self.button), n_cols)] + if header_buttons: + menu.insert(0, header_buttons) + if footer_buttons: + menu.append(footer_buttons) + return menu diff --git a/bot/helper/telegram_helper/message_utils.py b/bot/helper/telegram_helper/message_utils.py index 285b6550e06..b5cafcabb86 100644 --- a/bot/helper/telegram_helper/message_utils.py +++ b/bot/helper/telegram_helper/message_utils.py @@ -1,3 +1,4 @@ +from telegram import InlineKeyboardMarkup from telegram.message import Message from telegram.update import Update import time @@ -15,12 +16,15 @@ def sendMessage(text: str, bot, update: Update): text=text, parse_mode='HTMl') except Exception as e: LOGGER.error(str(e)) +def sendMarkup(text: str, bot, update: Update, reply_markup: InlineKeyboardMarkup): + return bot.send_message(update.message.chat_id, + reply_to_message_id=update.message.message_id, + text=text, reply_markup=reply_markup, parse_mode='HTMl') - -def editMessage(text: str, message: Message): +def editMessage(text: str, message: Message, reply_markup=None): try: bot.edit_message_text(text=text, message_id=message.message_id, - chat_id=message.chat.id, + chat_id=message.chat.id,reply_markup=reply_markup, parse_mode='HTMl') except Exception as e: LOGGER.error(str(e)) diff --git a/bot/modules/clone.py b/bot/modules/clone.py index ede1de4add2..893d47a702f 100644 --- a/bot/modules/clone.py +++ b/bot/modules/clone.py @@ -14,9 +14,9 @@ def cloneNode(update,context): link = args[1] msg = sendMessage(f"Cloning: {link}",context.bot,update) gd = GoogleDriveHelper() - result = gd.clone(link) + result, button = gd.clone(link) deleteMessage(context.bot,msg) - sendMessage(result,context.bot,update) + sendMarkup(result,context.bot,update,button) else: sendMessage("Provide G-Drive Shareable Link to Clone.",context.bot,update) diff --git a/bot/modules/list.py b/bot/modules/list.py index f633749fe87..30266f7faaa 100644 --- a/bot/modules/list.py +++ b/bot/modules/list.py @@ -1,26 +1,27 @@ from telegram.ext import CommandHandler, run_async from bot.helper.mirror_utils.upload_utils.gdriveTools import GoogleDriveHelper from bot import LOGGER, dispatcher -from bot.helper.telegram_helper.message_utils import auto_delete_message, sendMessage +from bot.helper.telegram_helper.message_utils import sendMessage, sendMarkup, editMessage from bot.helper.telegram_helper.filters import CustomFilters import threading from bot.helper.telegram_helper.bot_commands import BotCommands @run_async def list_drive(update,context): - if update.message.text == f'/{BotCommands.ListCommand}': - sendMessage(f'Send a search key along with {BotCommands.ListCommand} command', context.bot, update) - message = update.message.text - search = message.split(' ',maxsplit=1)[1] - LOGGER.info(f"Searching: {search}") - gdrive = GoogleDriveHelper(None) - msg = gdrive.drive_list(search) - if msg: - reply_message = sendMessage(msg, context.bot, update) - else: - reply_message = sendMessage('No result found', context.bot, update) + try: + search = update.message.text.split(' ',maxsplit=1)[1] + LOGGER.info(f"Searching: {search}") + reply = sendMessage('Searching..... Please wait!', context.bot, update) + gdrive = GoogleDriveHelper(None) + msg, button = gdrive.drive_list(search) - threading.Thread(target=auto_delete_message, args=(context.bot, update.message, reply_message)).start() + if button: + editMessage(msg, reply, button) + else: + editMessage('No result found', reply, button) + + except IndexError: + sendMessage('Send a search key along with command', context.bot, update) list_handler = CommandHandler(BotCommands.ListCommand, list_drive,filters=CustomFilters.authorized_chat | CustomFilters.authorized_user) diff --git a/bot/modules/mirror.py b/bot/modules/mirror.py index c9f00416dc2..4a7876c7da6 100644 --- a/bot/modules/mirror.py +++ b/bot/modules/mirror.py @@ -1,5 +1,6 @@ import requests from telegram.ext import CommandHandler, run_async +from telegram import InlineKeyboardMarkup from bot import Interval, INDEX_URL, BLOCK_MEGA_LINKS from bot import dispatcher, DOWNLOAD_DIR, DOWNLOAD_STATUS_UPDATE_INTERVAL, download_dict, download_dict_lock @@ -18,6 +19,7 @@ from bot.helper.telegram_helper.bot_commands import BotCommands from bot.helper.telegram_helper.filters import CustomFilters from bot.helper.telegram_helper.message_utils import * +from bot.helper.telegram_helper import button_build import pathlib import os import subprocess @@ -137,26 +139,28 @@ def onUploadProgress(self): def onUploadComplete(self, link: str): with download_dict_lock: - msg = f'{download_dict[self.uid].name()} ({download_dict[self.uid].size()})' + msg = f'Filename : {download_dict[self.uid].name()}\nSize : {download_dict[self.uid].size()}' + buttons = button_build.ButtonMaker() + buttons.buildbutton("✨Drive Link✨", link) LOGGER.info(f'Done Uploading {download_dict[self.uid].name()}') if INDEX_URL is not None: share_url = requests.utils.requote_uri(f'{INDEX_URL}/{download_dict[self.uid].name()}') if os.path.isdir(f'{DOWNLOAD_DIR}/{self.uid}/{download_dict[self.uid].name()}'): share_url += '/' - msg += f'\n\nShareable link: here' + buttons.buildbutton("⚡Index Link⚡", share_url) if self.message.from_user.username: uname = f"@{self.message.from_user.username}" else: uname = f'{self.message.from_user.first_name}' if uname is not None: - msg += f'\ncc : {uname}' + msg += f'\n\ncc : {uname}' try: fs_utils.clean_download(download_dict[self.uid].path()) except FileNotFoundError: pass del download_dict[self.uid] count = len(download_dict) - sendMessage(msg, self.bot, self.update) + sendMarkup(msg, self.bot, self.update, InlineKeyboardMarkup(buttons.build_menu(2))) if count == 0: self.clean() else: diff --git a/requirements.txt b/requirements.txt index 65e1cd62d54..a36385a34a5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,3 +19,5 @@ natsort aiohttp speedtest-cli>=2.1.2 messages +lxml +telegraph