diff --git a/Dockerfile b/Dockerfile index 5fb7f5a..c447db9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,10 +3,12 @@ FROM ubuntu:18.04 WORKDIR /usr/src/app RUN chmod 777 /usr/src/app RUN apt-get -qq update -RUN apt-get -qq install -y aria2 python3 python3-pip \ +RUN apt-get -qq install -y aria2 python3 python3-pip rar unzip \ locales python3-lxml \ curl pv jq ffmpeg COPY requirements.txt . +COPY extract /usr/local/bin +RUN chmod +x /usr/local/bin/extract RUN pip3 install --no-cache-dir -r requirements.txt RUN locale-gen en_US.UTF-8 ENV LANG en_US.UTF-8 diff --git a/bot/__main__.py b/bot/__main__.py index adc0df0..b4ba553 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -65,6 +65,8 @@ 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.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/ext_utils/bot_utils.py b/bot/helper/ext_utils/bot_utils.py index 5998e53..a311ead 100644 --- a/bot/helper/ext_utils/bot_utils.py +++ b/bot/helper/ext_utils/bot_utils.py @@ -19,6 +19,7 @@ class MirrorStatus: STATUS_FAILED = "Failed. Cleaning download" STATUS_CANCELLED = "Cancelled" STATUS_ARCHIVING = "Archiving" + STATUS_EXTRACTING = "Extracting" PROGRESS_MAX_SIZE = 100 // 8 @@ -91,7 +92,7 @@ def get_readable_message(): for download in list(download_dict.values()): msg += f"{download.name()} - " msg += download.status() - if download.status() != MirrorStatus.STATUS_ARCHIVING: + if download.status() != MirrorStatus.STATUS_ARCHIVING and download.status() != MirrorStatus.STATUS_EXTRACTING: msg += f"\n{get_progress_bar_string(download)} {download.progress()} of " \ f"{download.size()}" \ f" at {download.speed()}, ETA: {download.eta()} " @@ -144,4 +145,4 @@ def new_thread(fn): thread = threading.Thread(target=fn, args=args, kwargs=kwargs) thread.start() return thread - return wrapper \ No newline at end of file + return wrapper diff --git a/bot/helper/ext_utils/fs_utils.py b/bot/helper/ext_utils/fs_utils.py index 0b92aa0..90951d6 100644 --- a/bot/helper/ext_utils/fs_utils.py +++ b/bot/helper/ext_utils/fs_utils.py @@ -56,6 +56,31 @@ def tar(org_path): return tar_path +def get_base_name(orig_path: str): + if orig_path.endswith(".tar.bz2"): + return orig_path.replace(".tar.bz2", "") + elif orig_path.endswith(".tar.gz"): + return orig_path.replace(".tar.gz","") + elif orig_path.endswith(".bz2"): + return orig_path.replace(".bz2","") + elif orig_path.endswith(".gz"): + return orig_path.replace(".gz","") + elif orig_path.endswith(".tar"): + return orig_path.replace(".tar","") + elif orig_path.endswith(".tbz2"): + return orig_path.replace("tbz2","") + elif orig_path.endswith(".tgz"): + return orig_path.replace(".tgz","") + elif orig_path.endswith(".zip"): + return orig_path.replace(".zip","") + elif orig_path.endswith(".Z"): + return orig_path.replace(".Z","") + elif orig_path.endswith(".rar"): + return orig_path.replace(".rar","") + else: + return "unsupported" + + def get_mime_type(file_path): mime = magic.Magic(mime=True) mime_type = mime.from_file(file_path) diff --git a/bot/helper/mirror_utils/status_utils/aria_download_status.py b/bot/helper/mirror_utils/status_utils/aria_download_status.py index c3199f7..ef04a79 100644 --- a/bot/helper/mirror_utils/status_utils/aria_download_status.py +++ b/bot/helper/mirror_utils/status_utils/aria_download_status.py @@ -20,6 +20,7 @@ class AriaDownloadStatus(Status): self.message = listener.message self.last = None self.is_waiting = False + self.is_extracting = False def __update(self): self.__download = get_download(self.__gid) diff --git a/bot/helper/mirror_utils/status_utils/extract_status.py b/bot/helper/mirror_utils/status_utils/extract_status.py new file mode 100644 index 0000000..f7f5e59 --- /dev/null +++ b/bot/helper/mirror_utils/status_utils/extract_status.py @@ -0,0 +1,36 @@ +from .status import Status +from bot.helper.ext_utils.bot_utils import get_readable_file_size, MirrorStatus + + +class ExtractStatus(Status): + def __init__(self, name, path, size): + self.__name = name + self.__path = path + self.__size = size + + # The progress of Tar function cannot be tracked. So we just return dummy values. + # If this is possible in future,we should implement it + + def progress(self): + return '0' + + def speed(self): + return '0' + + def name(self): + return self.__name + + def path(self): + return self.__path + + def size(self): + return get_readable_file_size(self.__size) + + def eta(self): + return '0s' + + def status(self): + return MirrorStatus.STATUS_EXTRACTING + + def processed_bytes(self): + return 0 diff --git a/bot/helper/telegram_helper/bot_commands.py b/bot/helper/telegram_helper/bot_commands.py index fee3fa2..bd1af0c 100644 --- a/bot/helper/telegram_helper/bot_commands.py +++ b/bot/helper/telegram_helper/bot_commands.py @@ -2,6 +2,7 @@ class _BotCommands: def __init__(self): self.StartCommand = 'start' self.MirrorCommand = 'mirror' + self.UnzipMirrorCommand = 'unzipmirror' self.TarMirrorCommand = 'tarmirror' self.CancelMirror = 'cancel' self.CancelAllCommand = 'cancelall' diff --git a/bot/modules/mirror.py b/bot/modules/mirror.py index f6831fb..b253139 100644 --- a/bot/modules/mirror.py +++ b/bot/modules/mirror.py @@ -10,6 +10,7 @@ from bot.helper.mirror_utils.download_utils.aria2_download import AriaDownloadHe from bot.helper.mirror_utils.download_utils.direct_link_generator import direct_link_generator from bot.helper.mirror_utils.download_utils.telegram_downloader import TelegramDownloadHelper from bot.helper.mirror_utils.status_utils import listeners +from bot.helper.mirror_utils.status_utils.extract_status import ExtractStatus from bot.helper.mirror_utils.status_utils.tar_status import TarStatus from bot.helper.mirror_utils.status_utils.upload_status import UploadStatus from bot.helper.mirror_utils.upload_utils import gdriveTools @@ -24,11 +25,11 @@ ariaDlManager.start_listener() class MirrorListener(listeners.MirrorListeners): - - def __init__(self, bot, update, isTar=False, tag=None): + def __init__(self, bot, update, isTar=False,tag=None, extract=False): super().__init__(bot, update) self.isTar = isTar self.tag = tag + self.extract = extract def onDownloadStarted(self): pass @@ -62,6 +63,30 @@ class MirrorListener(listeners.MirrorListeners): LOGGER.info('File to archive not found!') self.onUploadError('Internal error occurred!!') return + elif self.extract: + download.is_extracting = True + + path = fs_utils.get_base_name(m_path) + if path != "unsupported": + LOGGER.info( + f"Extracting : {download_dict[self.uid].name()} " + ) + download_dict[self.uid] = ExtractStatus(name, m_path, size) + os.system(f"extract '{m_path}'") + if not os.path.exists(path): + self.onUploadError("Cannot extract file, check integrity of the file") + return + LOGGER.info( + f'got path : {path}' + ) + try: + os.remove(m_path) + LOGGER.info(f"Deleting archive : {m_path}") + except Exception as e: + LOGGER.error(str(e)) + else: + LOGGER.info("Not any valid archive, uploading file as it is.") + path = f'{DOWNLOAD_DIR}{self.uid}/{download_dict[self.uid].name()}' else: path = f'{DOWNLOAD_DIR}{self.uid}/{download_dict[self.uid].name()}' up_name = pathlib.PurePath(path).name @@ -145,8 +170,7 @@ class MirrorListener(listeners.MirrorListeners): else: update_all_messages() - -def _mirror(bot, update, isTar=False): +def _mirror(bot, update, isTar=False, extract=False): message_args = update.message.text.split(' ') try: link = message_args[1] @@ -186,7 +210,7 @@ def _mirror(bot, update, isTar=False): link = direct_link_generator(link) except DirectDownloadLinkException as e: LOGGER.info(f'{link}: {e}') - listener = MirrorListener(bot, update, isTar, tag) + listener = MirrorListener(bot, update, isTar, tag, extract) ariaDlManager.add_download(link, f'{DOWNLOAD_DIR}/{listener.uid}/',listener) sendStatusMessage(update, bot) if len(Interval) == 0: @@ -203,9 +227,17 @@ def tar_mirror(update, context): _mirror(context.bot, update, True) +@run_async +def unzip_mirror(update, context): + _mirror(context.bot,update, extract=True) + + mirror_handler = CommandHandler(BotCommands.MirrorCommand, mirror, filters=CustomFilters.authorized_chat | CustomFilters.authorized_user) tar_mirror_handler = CommandHandler(BotCommands.TarMirrorCommand, tar_mirror, filters=CustomFilters.authorized_chat | CustomFilters.authorized_user) +unzip_mirror_handler = CommandHandler(BotCommands.UnzipMirrorCommand, unzip_mirror, + filters=CustomFilters.authorized_chat | CustomFilters.authorized_user) dispatcher.add_handler(mirror_handler) dispatcher.add_handler(tar_mirror_handler) +dispatcher.add_handler(unzip_mirror_handler) diff --git a/extract b/extract new file mode 100755 index 0000000..db113eb --- /dev/null +++ b/extract @@ -0,0 +1,34 @@ +#!/bin/bash + +if [ $# -lt 1 ];then + echo "Usage: `basename $0` FILES" + exit 1 +fi + +extract () { + arg="$1" + cd $(dirname "$arg") + case "$arg" in + *.tar.bz2) + tar xjf "$arg" --one-top-level ;; + *.tar.gz) + tar xzf "$arg" --one-top-level ;; + *.bz2) bunzip2 "$arg" ;; + *.gz) gunzip "$arg" ;; + *.tar) tar xf "$arg" --one-top-level ;; + *.tbz2) tar xjf "$arg" --one-top-level ;; + *.tgz) tar xzf "$arg" --one-top-level ;; + *.zip) + a_dir=`expr "$arg" : '\(.*\).zip'` + unzip "$arg" -d "$a_dir" ;; + *.Z) uncompress "$arg" ;; + *.rar) + a_dir=`expr "$arg" : '\(.*\).rar'` ; + mkdir "$a_dir" ; + rar x "$arg" "$a_dir" ;; # 'rar' must to be installed + *) echo "'$arg' cannot be extracted via extract()" ;; + esac + cd - +} + +extract "$1"