diff --git a/bot/helper/ext_utils/bot_utils.py b/bot/helper/ext_utils/bot_utils.py
index 20b316c..a7ec1c3 100644
--- a/bot/helper/ext_utils/bot_utils.py
+++ b/bot/helper/ext_utils/bot_utils.py
@@ -23,6 +23,7 @@ PAGE_NO = 1
class MirrorStatus:
STATUS_UPLOADING = "Uploading...📤"
STATUS_DOWNLOADING = "Downloading...📥"
+ STATUS_CLONING = "Cloning...♻️"
STATUS_WAITING = "Queued...📝"
STATUS_FAILED = "Failed 🚫. Cleaning Download..."
STATUS_ARCHIVING = "Archiving...🔐"
@@ -123,6 +124,8 @@ def get_readable_message():
msg += f"\n{get_progress_bar_string(download)} {download.progress()}"
if download.status() == MirrorStatus.STATUS_DOWNLOADING:
msg += f"\nDownloaded: {get_readable_file_size(download.processed_bytes())} of {download.size()}"
+ elif download.status() == MirrorStatus.STATUS_CLONING:
+ msg += f"\nCloned: {get_readable_file_size(download.processed_bytes())} of {download.size()}"
else:
msg += f"\nUploaded: {get_readable_file_size(download.processed_bytes())} of {download.size()}"
msg += f"\nSpeed: {download.speed()}" \
@@ -134,7 +137,7 @@ def get_readable_message():
except:
pass
msg += f'\nUser: {download.message.from_user.first_name} ({download.message.from_user.id})'
- if download.status() == MirrorStatus.STATUS_DOWNLOADING:
+ if download.status() == MirrorStatus.STATUS_DOWNLOADING or download.status() == MirrorStatus.STATUS_CLONING:
msg += f"\nTo Stop: /{BotCommands.CancelMirror} {download.gid()}"
msg += "\n\n"
if STATUS_LIMIT is not None:
diff --git a/bot/helper/mirror_utils/status_utils/clone_status.py b/bot/helper/mirror_utils/status_utils/clone_status.py
new file mode 100644
index 0000000..f450ae7
--- /dev/null
+++ b/bot/helper/mirror_utils/status_utils/clone_status.py
@@ -0,0 +1,56 @@
+from .status import Status
+from bot.helper.ext_utils.bot_utils import MirrorStatus, get_readable_file_size, get_readable_time
+
+
+class CloneStatus(Status):
+ def __init__(self, obj, size, update, gid):
+ self.cobj = obj
+ self.__csize = size
+ self.message = update.message
+ self.__cgid = gid
+
+ def processed_bytes(self):
+ return self.cobj.transferred_size
+
+ def size_raw(self):
+ return self.__csize
+
+ def size(self):
+ return get_readable_file_size(self.__csize)
+
+ def status(self):
+ return MirrorStatus.STATUS_CLONING
+
+ def name(self):
+ return self.cobj.name
+
+ def gid(self) -> str:
+ return self.__cgid
+
+ def progress_raw(self):
+ try:
+ return self.cobj.transferred_size / self.__csize * 100
+ except ZeroDivisionError:
+ return 0
+
+ def progress(self):
+ return f'{round(self.progress_raw(), 2)}%'
+
+ def speed_raw(self):
+ """
+ :return: Download speed in Bytes/Seconds
+ """
+ return self.cobj.cspeed()
+
+ def speed(self):
+ return f'{get_readable_file_size(self.speed_raw())}/s'
+
+ def eta(self):
+ try:
+ seconds = (self.__csize - self.cobj.transferred_size) / self.speed_raw()
+ return f'{get_readable_time(seconds)}'
+ except ZeroDivisionError:
+ return '-'
+
+ def download(self):
+ return self.cobj
diff --git a/bot/helper/mirror_utils/upload_utils/gdriveTools.py b/bot/helper/mirror_utils/upload_utils/gdriveTools.py
index b2fab5d..2cc9427 100644
--- a/bot/helper/mirror_utils/upload_utils/gdriveTools.py
+++ b/bot/helper/mirror_utils/upload_utils/gdriveTools.py
@@ -22,7 +22,7 @@ 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, telegraph_token, BUTTON_FOUR_NAME, BUTTON_FOUR_URL, BUTTON_FIVE_NAME, BUTTON_FIVE_URL, BUTTON_SIX_NAME, BUTTON_SIX_URL, SHORTENER, SHORTENER_API, IMAGE_URL, VIEW_LINK
+ USE_SERVICE_ACCOUNTS, telegraph_token, BUTTON_FOUR_NAME, BUTTON_FOUR_URL, BUTTON_FIVE_NAME, BUTTON_FIVE_URL, BUTTON_SIX_NAME, BUTTON_SIX_URL, SHORTENER, SHORTENER_API, IMAGE_URL, VIEW_LINK
from bot.helper.ext_utils.bot_utils import *
from bot.helper.ext_utils.fs_utils import get_mime_type, get_path_size
@@ -44,17 +44,15 @@ class GoogleDriveHelper:
self.__G_DRIVE_DIR_BASE_DOWNLOAD_URL = "https://drive.google.com/drive/folders/{}"
self.__listener = listener
self.__service = self.authorize()
- self.__listener = listener
self._file_uploaded_bytes = 0
self._file_downloaded_bytes = 0
self.uploaded_bytes = 0
self.downloaded_bytes = 0
- self.UPDATE_INTERVAL = 5
self.start_time = 0
self.total_time = 0
self.dtotal_time = 0
- self._should_update = True
- self.is_uploading = True
+ self.is_downloading = False
+ self.is_cloning = False
self.is_cancelled = False
self.status = None
self.dstatus = None
@@ -66,12 +64,9 @@ class GoogleDriveHelper:
self.total_bytes = 0
self.total_files = 0
self.total_folders = 0
+ self.transferred_size = 0
self.sa_count = 0
- def cancel(self):
- self.is_cancelled = True
- self.is_uploading = False
-
def speed(self):
"""
It calculates the average upload speed and returns it in bytes/seconds unit
@@ -86,7 +81,13 @@ class GoogleDriveHelper:
try:
return self.downloaded_bytes / self.dtotal_time
except ZeroDivisionError:
- return 0
+ return 0
+
+ def cspeed(self):
+ try:
+ return self.transferred_size / int(time.time() - self.start_time)
+ except ZeroDivisionError:
+ return 0
@staticmethod
def getIdFromUrl(link: str):
@@ -236,7 +237,6 @@ class GoogleDriveHelper:
file_path = f"{file_dir}/{file_name}"
size = get_readable_file_size(get_path_size(file_path))
LOGGER.info("Uploading File: " + file_path)
- self.start_time = time.time()
self.updater = setInterval(self.update_interval, self._on_upload_progress)
if os.path.isfile(file_path):
try:
@@ -275,7 +275,6 @@ class GoogleDriveHelper:
return
finally:
self.updater.cancel()
- LOGGER.info(download_dict)
files = self.total_files
folders = self.total_folders
typ = self.typee
@@ -338,7 +337,8 @@ class GoogleDriveHelper:
return files
def clone(self, link):
- self.transferred_size = 0
+ self.is_cloning = True
+ self.start_time = time.time()
self.total_files = 0
self.total_folders = 0
if USE_SERVICE_ACCOUNTS:
@@ -355,11 +355,16 @@ class GoogleDriveHelper:
if meta.get("mimeType") == self.__G_DRIVE_DIR_MIME_TYPE:
dir_id = self.create_directory(meta.get('name'), parent_id)
self.cloneFolder(meta.get('name'), meta.get('name'), meta.get('id'), dir_id)
+ durl = self.__G_DRIVE_DIR_BASE_DOWNLOAD_URL.format(dir_id)
+ if self.is_cancelled:
+ LOGGER.info("Deleting cloned data from drive...")
+ msg = self.deletefile(durl)
+ LOGGER.info(f"{msg}")
+ return "Your clone has been stopped and cloned data has been deleted!", "cancelled"
msg += f'Filename: {meta.get("name")}\nSize: {get_readable_file_size(self.transferred_size)}'
msg += f'\nType: Folder'
msg += f'\nSubFolders: {self.total_folders}'
msg += f'\nFiles: {self.total_files}'
- durl = self.__G_DRIVE_DIR_BASE_DOWNLOAD_URL.format(dir_id)
buttons = button_build.ButtonMaker()
if SHORTENER is not None and SHORTENER_API is not None:
surl = requests.get(f'https://{SHORTENER}/api?api={SHORTENER_API}&url={durl}&format=text').text
@@ -723,6 +728,7 @@ class GoogleDriveHelper:
except TypeError:
pass
clonesize = self.total_bytes
+ files = self.total_files
except Exception as err:
err = str(err).replace('>', '').replace('<', '')
LOGGER.error(err)
@@ -731,13 +737,13 @@ class GoogleDriveHelper:
else:
msg = f"Error.\n{err}"
return msg, "", ""
- return "", clonesize, name
+ return "", clonesize, name, files
def download(self, link):
+ self.is_downloading = True
file_id = self.getIdFromUrl(link)
if USE_SERVICE_ACCOUNTS:
self.service_account_count = len(os.listdir("accounts"))
- self.start_time = time.time()
self.updater = setInterval(self.update_interval, self._on_download_progress)
try:
meta = self.getFileMetadata(file_id)
@@ -834,5 +840,8 @@ class GoogleDriveHelper:
def cancel_download(self):
self.is_cancelled = True
- LOGGER.info(f"Cancelling Download: {self.name}")
- self.__listener.onDownloadError('Download stopped by user!')
+ if self.is_downloading:
+ LOGGER.info(f"Cancelling Download: {self.name}")
+ self.__listener.onDownloadError('Download stopped by user!')
+ elif self.is_cloning:
+ LOGGER.info(f"Cancelling Clone: {self.name}")
diff --git a/bot/helper/telegram_helper/message_utils.py b/bot/helper/telegram_helper/message_utils.py
index 7f4ae4b..19b081a 100644
--- a/bot/helper/telegram_helper/message_utils.py
+++ b/bot/helper/telegram_helper/message_utils.py
@@ -93,7 +93,7 @@ def update_all_messages():
uldl_bytes += float(speedy.split('M')[0]) * 1048576
dlspeed = get_readable_file_size(dlspeed_bytes)
ulspeed = get_readable_file_size(uldl_bytes)
- msg += f"\nFREE: {free} | UPTIME: {currentTime}\nDL: {dlspeed}ps 🔻 | UL: {ulspeed}ps 🔺\n"
+ msg += f"\nFREE: {free} | UPTIME: {currentTime}\nDL: {dlspeed}/s 🔻 | UL: {ulspeed}/s 🔺\n"
with status_reply_dict_lock:
for chat_id in list(status_reply_dict.keys()):
if status_reply_dict[chat_id] and msg != status_reply_dict[chat_id].text:
@@ -134,7 +134,7 @@ def sendStatusMessage(msg, bot):
uldl_bytes += float(speedy.split('M')[0]) * 1048576
dlspeed = get_readable_file_size(dlspeed_bytes)
ulspeed = get_readable_file_size(uldl_bytes)
- progress += f"\nFREE: {free} | UPTIME: {currentTime}\nDL: {dlspeed}ps 🔻 | UL: {ulspeed}ps 🔺\n"
+ progress += f"\nFREE: {free} | UPTIME: {currentTime}\nDL: {dlspeed}/s 🔻 | UL: {ulspeed}/s 🔺\n"
with status_reply_dict_lock:
if msg.message.chat.id in list(status_reply_dict.keys()):
try:
diff --git a/bot/modules/cancel_mirror.py b/bot/modules/cancel_mirror.py
index a11e1ca..6385ac9 100644
--- a/bot/modules/cancel_mirror.py
+++ b/bot/modules/cancel_mirror.py
@@ -72,7 +72,6 @@ def cancel_all(update, context):
count += 1
else:
break
- delete_all_messages()
sendMessage(f'{count} Download(s) has been Cancelled!', context.bot, update)
diff --git a/bot/modules/clone.py b/bot/modules/clone.py
index df4f909..cae1aaa 100644
--- a/bot/modules/clone.py
+++ b/bot/modules/clone.py
@@ -1,56 +1,84 @@
from telegram.ext import CommandHandler
-from bot.helper.mirror_utils.upload_utils.gdriveTools import GoogleDriveHelper
-from bot.helper.telegram_helper.message_utils import sendMarkup, deleteMessage, sendMessage
+from bot.helper.mirror_utils.upload_utils import gdriveTools
+from bot.helper.telegram_helper.message_utils import *
from bot.helper.telegram_helper.filters import CustomFilters
from bot.helper.telegram_helper.bot_commands import BotCommands
-from bot import dispatcher, LOGGER, CLONE_LIMIT, STOP_DUPLICATE_CLONE
-from bot.helper.ext_utils.bot_utils import get_readable_file_size
+from bot.helper.mirror_utils.status_utils.clone_status import CloneStatus
+from bot import dispatcher, LOGGER, CLONE_LIMIT, STOP_DUPLICATE_CLONE, download_dict, download_dict_lock, Interval, DOWNLOAD_STATUS_UPDATE_INTERVAL
+from bot.helper.ext_utils.bot_utils import get_readable_file_size, setInterval
+import random
+import string
def cloneNode(update, context):
args = update.message.text.split(" ", maxsplit=1)
if len(args) > 1:
link = args[1]
- gd = GoogleDriveHelper()
- if CLONE_LIMIT is not None or STOP_DUPLICATE_CLONE:
- res, clonesize, name = gd.clonehelper(link)
- if res != "":
- sendMessage(res, context.bot, update)
- return
- if STOP_DUPLICATE_CLONE:
- LOGGER.info(f"Checking File/Folder if already in Drive...")
- smsg, button = gd.drive_list(name)
- if smsg:
- msg3 = "File/Folder is already available in Drive.\nHere are the search results:"
- sendMarkup(msg3, context.bot, update, button)
+ gd = gdriveTools.GoogleDriveHelper()
+ res, clonesize, name, files = gd.clonehelper(link)
+ if res != "":
+ sendMessage(res, context.bot, update)
+ return
+ if STOP_DUPLICATE_CLONE:
+ LOGGER.info(f"Checking File/Folder if already in Drive...")
+ smsg, button = gd.drive_list(name)
+ if smsg:
+ msg3 = "File/Folder is already available in Drive.\nHere are the search results:"
+ sendMarkup(msg3, context.bot, update, button)
+ return
+ if CLONE_LIMIT is not None:
+ LOGGER.info(f"Checking File/Folder Size...")
+ limit = CLONE_LIMIT
+ limit = limit.split(' ', maxsplit=1)
+ limitint = int(limit[0])
+ msg2 = f'Failed, Clone limit is {CLONE_LIMIT}.\nYour File/Folder size is {get_readable_file_size(clonesize)}.'
+ if 'G' in limit[1] or 'g' in limit[1]:
+ if clonesize > limitint * 1024**3:
+ sendMessage(msg2, context.bot, update)
return
- if CLONE_LIMIT is not None:
- LOGGER.info(f"Checking File/Folder Size...")
- limit = CLONE_LIMIT
- limit = limit.split(' ', maxsplit=1)
- limitint = int(limit[0])
- msg2 = f'Failed, Clone limit is {CLONE_LIMIT}.\nYour File/Folder size is {get_readable_file_size(clonesize)}.'
- if 'G' in limit[1] or 'g' in limit[1]:
- if clonesize > limitint * 1024**3:
- sendMessage(msg2, context.bot, update)
- return
- elif 'T' in limit[1] or 't' in limit[1]:
- if clonesize > limitint * 1024**4:
- sendMessage(msg2, context.bot, update)
- return
- msg = sendMessage(f"Cloning: {link}", context.bot, update)
- result, button = gd.clone(link)
- deleteMessage(context.bot, msg)
- if button == "":
- sendMessage(result, context.bot, update)
+ elif 'T' in limit[1] or 't' in limit[1]:
+ if clonesize > limitint * 1024**4:
+ sendMessage(msg2, context.bot, update)
+ return
+ if files < 15:
+ msg = sendMessage(f"Cloning: {link}", context.bot, update)
+ result, button = gd.clone(link)
+ deleteMessage(context.bot, msg)
+ else:
+ drive = gdriveTools.GoogleDriveHelper(name)
+ gid = ''.join(random.SystemRandom().choices(string.ascii_letters + string.digits, k=12))
+ clone_status = CloneStatus(drive, clonesize, update, gid)
+ with download_dict_lock:
+ download_dict[update.message.message_id] = clone_status
+ if len(Interval) == 0:
+ Interval.append(setInterval(DOWNLOAD_STATUS_UPDATE_INTERVAL, update_all_messages))
+ sendStatusMessage(update, context.bot)
+ result, button = drive.clone(link)
+ if update.message.from_user.username:
+ uname = f'@{update.message.from_user.username}'
+ else:
+ uname = f'{update.message.from_user.first_name}'
+ if uname is not None:
+ cc = f'\n\ncc: {uname}'
+ men = f'{uname} '
+ if button == "cancelled":
+ sendMessage(men + result, context.bot, update)
+ elif button == "":
+ sendMessage(men + result, context.bot, update)
else:
- if update.message.from_user.username:
- uname = f'@{update.message.from_user.username}'
- else:
- uname = f'{update.message.from_user.first_name}'
- if uname is not None:
- cc = f'\n\ncc: {uname}'
sendMarkup(result + cc, context.bot, update, button)
+ try:
+ with download_dict_lock:
+ del download_dict[update.message.message_id]
+ count = len(download_dict)
+ if count == 0:
+ Interval[0].cancel()
+ del Interval[0]
+ delete_all_messages()
+ else:
+ update_all_messages()
+ except IndexError:
+ pass
else:
sendMessage('Provide G-Drive Shareable Link to Clone.', context.bot, update)
diff --git a/bot/modules/mirror.py b/bot/modules/mirror.py
index 0fca8ec..14b59dd 100644
--- a/bot/modules/mirror.py
+++ b/bot/modules/mirror.py
@@ -302,7 +302,7 @@ def _mirror(bot, update, isTar=False, extract=False):
if not isTar and not extract:
sendMessage(f"Use /{BotCommands.CloneCommand} to clone Google Drive file/folder\nUse /{BotCommands.TarMirrorCommand} to make tar of Google Drive folder\nUse /{BotCommands.UnzipMirrorCommand} to extracts archive Google Drive file", bot, update)
return
- res, size, name = gdriveTools.GoogleDriveHelper().clonehelper(link)
+ res, size, name, files = gdriveTools.GoogleDriveHelper().clonehelper(link)
if res != "":
sendMessage(res, bot, update)
return