From b6feb5f5530422a8e0b9851bbbda0198e95dcb12 Mon Sep 17 00:00:00 2001 From: anasty17 Date: Sun, 1 Jan 2023 05:42:12 +0200 Subject: [PATCH] Media Group for all files - other minor fixes Signed-off-by: anasty17 --- README.md | 4 +- bot/helper/ext_utils/fs_utils.py | 21 +- .../upload_utils/pyrogramEngine.py | 278 +++++++++--------- bot/helper/telegram_helper/message_utils.py | 18 +- bot/modules/bot_settings.py | 6 +- bot/modules/clone.py | 34 ++- bot/modules/listener.py | 6 +- bot/modules/mirror_leech.py | 56 ++-- bot/modules/users_settings.py | 46 +-- bot/modules/ytdlp.py | 38 ++- 10 files changed, 271 insertions(+), 236 deletions(-) diff --git a/README.md b/README.md index 0e07cb48203..b476ae220a8 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ In each single file there is a major change from base code, it's almost totaly d - 4GB file upload with premium account - Upload all files to specific superGroup/channel. - Leech Split size and equal split size settings for each user -- Ability to upload documents and videos parts in media group. Setting for each user +- Ability to leech files in media group. Setting for each user ### Google - Stop duplicates for all tasks except yt-dlp tasks - Download from Google Drive @@ -182,7 +182,7 @@ Fill up rest of the fields. Meaning of each field is discussed below. **NOTE**: - `LEECH_SPLIT_SIZE`: Size of split in bytes. Default is `2GB`. Default is `4GB` if your account is premium. `Int` - `AS_DOCUMENT`: Default type of Telegram file upload. Default is `False` mean as media. `Bool` - `EQUAL_SPLITS`: Split files larger than **LEECH_SPLIT_SIZE** into equal parts size (Not working with zip cmd). Default is `False`. `Bool` -- `MEDIA_GROUP`: View Uploaded parts of videos or documents in media group. Default is `False`. `Bool` +- `MEDIA_GROUP`: View Uploaded files in media group. Default is `False`. `Bool`.**NOTE**: Some files will end without any reply, it's hard to manage. Maybe in future i will fix it. - `LEECH_FILENAME_PREFIX`: Add custom word to leeched file name. `Str` - `DUMP_CHAT`: Chat ID. Upload files to specific chat. `str`. **NOTE**: Only available for superGroup/channel. Add `-100` before channel/superGroup id. In short don't add bot id or your id! - `USER_SESSION_STRING`: To download/upload from your telegram account. If you own premium account. To generate session string use this command `python3 generate_string_session.py` after mounting repo folder for sure. `Str`. **NOTE**: You can't use bot with private message. Use it with superGroup. diff --git a/bot/helper/ext_utils/fs_utils.py b/bot/helper/ext_utils/fs_utils.py index d692483eb15..006ef33cd80 100644 --- a/bot/helper/ext_utils/fs_utils.py +++ b/bot/helper/ext_utils/fs_utils.py @@ -128,10 +128,10 @@ def split_file(path, size, file_, dirpath, split_size, listener, start_time=0, i if not ospath.exists(dirpath): mkdir(dirpath) user_id = listener.message.from_user.id - user_dict = user_data.get(user_id, False) - leech_split_size = user_dict and user_dict.get('split_size') or config_dict['LEECH_SPLIT_SIZE'] + user_dict = user_data.get(user_id, {}) + leech_split_size = user_dict.get('split_size') or config_dict['LEECH_SPLIT_SIZE'] parts = ceil(size/leech_split_size) - if (user_dict and user_dict.get('equal_splits') or config_dict['EQUAL_SPLITS']) and not inLoop: + if (user_dict.get('equal_splits') or config_dict['EQUAL_SPLITS']) and not inLoop: split_size = ceil(size/parts) + 1000 if get_media_streams(path)[0]: duration = get_media_info(path)[0] @@ -234,14 +234,19 @@ def get_media_streams(path): is_video = False is_audio = False + is_image = False mime_type = get_mime_type(path) if mime_type.startswith('audio'): is_audio = True - return is_video, is_audio + return is_video, is_audio, is_image + + if mime_type.startswith('image'): + is_image = True + return is_video, is_audio, is_image if path.endswith('.bin') or not mime_type.startswith('video') and not mime_type.endswith('octet-stream'): - return is_video, is_audio + return is_video, is_audio, is_image try: result = check_output(["ffprobe", "-hide_banner", "-loglevel", "error", "-print_format", @@ -249,12 +254,12 @@ def get_media_streams(path): except Exception as e: if not mime_type.endswith('octet-stream'): LOGGER.error(f'{e}. Mostly file not found!') - return is_video, is_audio + return is_video, is_audio, is_image fields = eval(result).get('streams') if fields is None: LOGGER.error(f"get_media_streams: {result}") - return is_video, is_audio + return is_video, is_audio, is_image for stream in fields: if stream.get('codec_type') == 'video': @@ -262,5 +267,5 @@ def get_media_streams(path): elif stream.get('codec_type') == 'audio': is_audio = True - return is_video, is_audio + return is_video, is_audio, is_image diff --git a/bot/helper/mirror_utils/upload_utils/pyrogramEngine.py b/bot/helper/mirror_utils/upload_utils/pyrogramEngine.py index adfc1a24cf3..1f60cac1865 100644 --- a/bot/helper/mirror_utils/upload_utils/pyrogramEngine.py +++ b/bot/helper/mirror_utils/upload_utils/pyrogramEngine.py @@ -1,11 +1,11 @@ from logging import getLogger, ERROR from os import remove as osremove, walk, path as ospath, rename as osrename from time import time, sleep -from pyrogram.types import InputMediaVideo, InputMediaDocument +from pyrogram.types import InputMediaVideo, InputMediaDocument, InputMediaAudio, InputMediaPhoto from pyrogram.errors import FloodWait, RPCError from PIL import Image from threading import RLock -from re import search as re_search +from tenacity import retry, wait_exponential, stop_after_attempt, retry_if_exception_type, RetryError from bot import config_dict, user_data, GLOBAL_EXTENSION_FILTER, app from bot.helper.ext_utils.fs_utils import take_ss, get_media_info, get_media_streams, clean_unwanted @@ -34,57 +34,61 @@ def __init__(self, name=None, path=None, size=0, listener=None): self.__resource_lock = RLock() self.__is_corrupted = False self.__size = size - self.__in_media_group = False - self.__media_dict = {'videos': {}, 'documents': {}} + self.__media_dict = {'videos': {}, 'documents': {}, 'audios': {}, 'photos': {}} self.__msg_to_reply() self.__user_settings() def upload(self, o_files, m_size): for dirpath, subdir, files in sorted(walk(self.__path)): - for file_ in sorted(files): - up_path = ospath.join(dirpath, file_) - f_size = ospath.getsize(up_path) - if self.__listener.seed and file_ in o_files and f_size in m_size: - continue - if not file_.lower().endswith(tuple(GLOBAL_EXTENSION_FILTER)): + for file_ in sorted(files, key=ospath.splitext): + try: + if file_.lower().endswith(tuple(GLOBAL_EXTENSION_FILTER)): + continue + up_path = ospath.join(dirpath, file_) + f_size = ospath.getsize(up_path) + if self.__listener.seed and file_ in o_files and f_size in m_size: + continue self.__total_files += 1 - try: - if f_size == 0: - LOGGER.error(f"{up_path} size is zero, telegram don't upload zero size files") - self.__corrupted += 1 - continue - except Exception as e: - if self.__is_cancelled: - return - LOGGER.error(e) + if f_size == 0: + LOGGER.error(f"{up_path} size is zero, telegram don't upload zero size files") + self.__corrupted += 1 continue - if self.__in_media_group: + if self.__is_cancelled: + return + if self.__media_group: group_lists = [x for v in self.__media_dict.values() for x in v.keys()] - match = re_search(r'.+(?=\.0*\d+$)|.+(?=\.part\d+\..+)', file_) - if match and not match.group(0) in group_lists: + if dirpath not in group_lists: for key, value in list(self.__media_dict.items()): - for pname, msgs in list(value.items()): + for subkey, msgs in list(value.items()): if len(msgs) > 1: - self.__send_media_group(pname, key, msgs) - self.__in_media_group = False - self.__upload_file(up_path, file_, dirpath) + self.__send_media_group(subkey, key, msgs) + up_path, cap_mono = self.__prepare_file(up_path, file_, dirpath) + self._last_uploaded = 0 + self.__upload_file(up_path, dirpath, cap_mono) + if not self.__is_cancelled and \ + (not self.__listener.seed or self.__listener.newDir or dirpath.endswith("splited_files_mltb")): + osremove(up_path) if self.__is_cancelled: return - if (not self.__listener.isPrivate or config_dict['DUMP_CHAT']) and not self.__is_corrupted and \ - not self.__in_media_group: + if (not self.__listener.isPrivate or config_dict['DUMP_CHAT']) and not self.__is_corrupted: self.__msgs_dict[self.__sent_msg.link] = file_ - self._last_uploaded = 0 sleep(1) + except Exception as err: + if isinstance(err, RetryError): + LOGGER.info(f"Total Attempts: {err.last_attempt.attempt_number}") + else: + LOGGER.error(f"{err}. Path: {up_path}") + continue for key, value in list(self.__media_dict.items()): - for pname, msgs in list(value.items()): + for subkey, msgs in list(value.items()): if len(msgs) > 1: - self.__send_media_group(pname, key, msgs) - elif not self.__listener.isPrivate or config_dict['DUMP_CHAT']: - self.__msgs_dict[msgs[0].link] = msgs[0].caption + self.__send_media_group(subkey, key, msgs) + if self.__is_cancelled: + return if self.__listener.seed and not self.__listener.newDir: clean_unwanted(self.__path) if self.__total_files == 0: - self.__listener.onUploadError("No files to upload. In case you have filled EXTENSION_FILTER, then check if all file have those extensions or not.") + self.__listener.onUploadError("No files to upload. In case you have filled EXTENSION_FILTER, then check if all files have those extensions or not.") return if self.__total_files <= self.__corrupted: self.__listener.onUploadError('Files Corrupted or unable to upload. Check logs!') @@ -93,70 +97,28 @@ def upload(self, o_files, m_size): size = get_readable_file_size(self.__size) self.__listener.onUploadComplete(None, size, self.__msgs_dict, self.__total_files, self.__corrupted, self.name) - def __upload_file(self, up_path, file_, dirpath): + def __prepare_file(self, up_path, file_, dirpath): if LEECH_FILENAME_PREFIX := config_dict['LEECH_FILENAME_PREFIX']: cap_mono = f"{LEECH_FILENAME_PREFIX} {file_}" - file_ = f"{LEECH_FILENAME_PREFIX} {file_}" - new_path = ospath.join(dirpath, file_) + new_path = ospath.join(dirpath, f"{LEECH_FILENAME_PREFIX} {file_}") osrename(up_path, new_path) up_path = new_path else: cap_mono = f"{file_}" - notMedia = False + return up_path, cap_mono + + @retry(wait=wait_exponential(multiplier=2, min=4, max=8), stop=stop_after_attempt(3), + retry=retry_if_exception_type(Exception)) + def __upload_file(self, up_path, dirpath, cap_mono, force_document=False): + if self.__thumb is not None and not ospath.lexists(self.__thumb): + self.__thumb = None thumb = self.__thumb self.__is_corrupted = False try: - is_video, is_audio = get_media_streams(up_path) - if not self.__as_doc: - if is_video: - duration = get_media_info(up_path)[0] - if thumb is None: - thumb = take_ss(up_path, duration) - if self.__is_cancelled: - if self.__thumb is None and thumb is not None and ospath.lexists(thumb): - osremove(thumb) - return - if thumb is not None: - with Image.open(thumb) as img: - width, height = img.size - else: - width = 480 - height = 320 - if not file_.upper().endswith(("MKV", "MP4")): - file_ = f"{ospath.splitext(file_)[0]}.mp4" - new_path = ospath.join(dirpath, file_) - osrename(up_path, new_path) - up_path = new_path - self.__sent_msg = self.__sent_msg.reply_video(video=up_path, - quote=True, - caption=cap_mono, - duration=duration, - width=width, - height=height, - thumb=thumb, - supports_streaming=True, - disable_notification=True, - progress=self.__upload_progress) - elif is_audio: - duration , artist, title = get_media_info(up_path) - self.__sent_msg = self.__sent_msg.reply_audio(audio=up_path, - quote=True, - caption=cap_mono, - duration=duration, - performer=artist, - title=title, - thumb=thumb, - disable_notification=True, - progress=self.__upload_progress) - elif file_.upper().endswith(IMAGE_SUFFIXES): - self.__sent_msg = self.__sent_msg.reply_photo(photo=up_path, - quote=True, - caption=cap_mono, - disable_notification=True, - progress=self.__upload_progress) - else: - notMedia = True - if self.__as_doc or notMedia: + is_video, is_audio, is_image = get_media_streams(up_path) + is_image = is_image or up_path.upper().endswith(IMAGE_SUFFIXES) + if self.__as_doc or force_document or (not is_video and not is_audio and not is_image): + key = 'documents' if is_video and thumb is None: thumb = take_ss(up_path, None) if self.__is_cancelled: @@ -169,40 +131,74 @@ def __upload_file(self, up_path, file_, dirpath): caption=cap_mono, disable_notification=True, progress=self.__upload_progress) - - if self.__media_group and (self.__as_doc or notMedia or is_video): - if match := re_search(r'.+(?=\.0*\d+$)|.+(?=\.part\d+\..+)', file_): - pname = match.group(0) - key = 'documents' if self.__as_doc or notMedia else 'videos' - if pname in self.__media_dict[key].keys(): - self.__media_dict[key][pname].append(self.__sent_msg) - else: - self.__media_dict[key][pname] = [self.__sent_msg] - msgs = self.__media_dict[key][pname] - if len(msgs) == 10: - self.__send_media_group(pname, key, msgs) - else: - self.__in_media_group = True - + elif is_video: + key = 'videos' + duration = get_media_info(up_path)[0] + if thumb is None: + thumb = take_ss(up_path, duration) + if self.__is_cancelled: + if self.__thumb is None and thumb is not None and ospath.lexists(thumb): + osremove(thumb) + return + if thumb is not None: + with Image.open(thumb) as img: + width, height = img.size + else: + width = 480 + height = 320 + if not up_path.upper().endswith(("MKV", "MP4")): + new_path = f"{up_path.rsplit('.', 1)[0]}.mp4" + osrename(up_path, new_path) + up_path = new_path + self.__sent_msg = self.__sent_msg.reply_video(video=up_path, + quote=True, + caption=cap_mono, + duration=duration, + width=width, + height=height, + thumb=thumb, + supports_streaming=True, + disable_notification=True, + progress=self.__upload_progress) + elif is_audio: + key = 'audios' + duration , artist, title = get_media_info(up_path) + self.__sent_msg = self.__sent_msg.reply_audio(audio=up_path, + quote=True, + caption=cap_mono, + duration=duration, + performer=artist, + title=title, + thumb=thumb, + disable_notification=True, + progress=self.__upload_progress) + elif is_image: + key = 'photos' + self.__sent_msg = self.__sent_msg.reply_photo(photo=up_path, + quote=True, + caption=cap_mono, + disable_notification=True, + progress=self.__upload_progress) + if self.__media_group and not self.__sent_msg.animation: + if dirpath in self.__media_dict[key].keys(): + self.__media_dict[key][dirpath].append(self.__sent_msg) + else: + self.__media_dict[key][dirpath] = [self.__sent_msg] + msgs = self.__media_dict[key][dirpath] + if len(msgs) == 10: + self.__send_media_group(dirpath, key, msgs) except FloodWait as f: LOGGER.warning(str(f)) sleep(f.value) - except RPCError as e: - LOGGER.error(f"RPCError: {e} Path: {up_path}") - self.__corrupted += 1 - self.__is_corrupted = True except Exception as err: - LOGGER.error(f"{err} Path: {up_path}") - self.__corrupted += 1 - self.__is_corrupted = True - if self.__thumb is None and thumb is not None and ospath.lexists(thumb): - osremove(thumb) - if not self.__is_cancelled and \ - (not self.__listener.seed or self.__listener.newDir or dirpath.endswith("splited_files_mltb")): - try: - osremove(up_path) - except: - pass + err_type = "RPCError: " if isinstance(err, RPCError) else "" + LOGGER.error(f"{err_type}{err}. Path: {up_path}") + if self.__thumb is None and thumb is not None and ospath.lexists(thumb): + osremove(thumb) + if 'Telegram says: [400' in str(err) and key != 'documents': + LOGGER.error(f"Retrying As Document. Path: {up_path}") + return self.__upload_file(up_path, dirpath, cap_mono, True) + raise err def __upload_progress(self, current, total): if self.__is_cancelled: @@ -215,9 +211,9 @@ def __upload_progress(self, current, total): def __user_settings(self): user_id = self.__listener.message.from_user.id - user_dict = user_data.get(user_id, False) - self.__as_doc = user_dict and user_dict.get('as_doc', False) or config_dict['AS_DOCUMENT'] - self.__media_group = user_dict and user_dict.get('media_group', False) or config_dict['MEDIA_GROUP'] + user_dict = user_data.get(user_id, {}) + self.__as_doc = user_dict.get('as_doc') or config_dict['AS_DOCUMENT'] + self.__media_group = user_dict.get('media_group') or config_dict['MEDIA_GROUP'] if not ospath.lexists(self.__thumb): self.__thumb = None @@ -231,29 +227,35 @@ def __msg_to_reply(self): else: self.__sent_msg = app.get_messages(self.__listener.message.chat.id, self.__listener.uid) - def __get_input_media(self, pname, key): + def __get_input_media(self, subkey, key): rlist = [] - for msg in self.__media_dict[key][pname]: + for msg in self.__media_dict[key][subkey]: if key == 'videos': input_media = InputMediaVideo(media=msg.video.file_id, caption=msg.caption) - else: + elif key == 'documents': input_media = InputMediaDocument(media=msg.document.file_id, caption=msg.caption) + elif key == 'photos': + input_media = InputMediaPhoto(media=msg.photo.file_id, caption=msg.caption) + else: + input_media = InputMediaAudio(media=msg.audio.file_id, caption=msg.caption) rlist.append(input_media) return rlist - def __send_media_group(self, pname, key, msgs): - reply_to_message_id = msgs[0].reply_to_message_id - msgs_list = app.send_media_group(chat_id=self.__sent_msg.chat.id, - media=self.__get_input_media(pname, key), - disable_notification=True, - reply_to_message_id=reply_to_message_id) - for msg in msgs: - msg.delete() - del self.__media_dict[key][pname] - if not self.__listener.isPrivate or config_dict['DUMP_CHAT']: - for m in msgs_list: - self.__msgs_dict[m.link] = m.caption + ' (Grouped)' - self.__sent_msg = msgs_list[-1] + def __send_media_group(self, subkey, key, msgs): + reply_to_message_id = msgs[0].reply_to_message_id + msgs_list = app.send_media_group(chat_id=self.__sent_msg.chat.id, + media=self.__get_input_media(subkey, key), + disable_notification=True, + reply_to_message_id=reply_to_message_id) + for msg in msgs: + if msg.link in self.__msgs_dict: + del self.__msgs_dict[msg.link] + msg.delete() + del self.__media_dict[key][subkey] + if not self.__listener.isPrivate or config_dict['DUMP_CHAT']: + for m in msgs_list: + self.__msgs_dict[m.link] = m.caption + self.__sent_msg = msgs_list[-1] @property def speed(self): diff --git a/bot/helper/telegram_helper/message_utils.py b/bot/helper/telegram_helper/message_utils.py index 73ade0780fe..ac248ce9462 100644 --- a/bot/helper/telegram_helper/message_utils.py +++ b/bot/helper/telegram_helper/message_utils.py @@ -1,7 +1,7 @@ from time import sleep, time from telegram.error import RetryAfter from pyrogram.errors import FloodWait -from os import remove +from io import BytesIO from bot import config_dict, LOGGER, status_reply_dict, status_reply_dict_lock, Interval, bot, rss_session from bot.helper.ext_utils.bot_utils import get_readable_message, setInterval @@ -72,17 +72,15 @@ def deleteMessage(bot, message): def sendLogFile(bot, message): with open('log.txt', 'rb') as f: - bot.sendDocument(document=f, filename=f.name, - reply_to_message_id=message.message_id, - chat_id=message.chat_id) + bot.sendDocument(document=f, filename=f.name, reply_to_message_id=message.message_id, + chat_id=message.chat_id) -def sendFile(bot, message, name, caption=""): +def sendFile(bot, message, txt, fileName, caption=""): try: - with open(name, 'rb') as f: - bot.sendDocument(document=f, filename=f.name, reply_to_message_id=message.message_id, - caption=caption, chat_id=message.chat_id) - remove(name) - return + with BytesIO(str.encode(txt)) as document: + document.name = fileName + return bot.sendDocument(document=document, reply_to_message_id=message.message_id, + caption=caption, chat_id=message.chat_id) except RetryAfter as r: LOGGER.warning(str(r)) sleep(r.retry_after * 1.5) diff --git a/bot/modules/bot_settings.py b/bot/modules/bot_settings.py index c883e1028e4..0b2f6600127 100644 --- a/bot/modules/bot_settings.py +++ b/bot/modules/bot_settings.py @@ -742,10 +742,8 @@ def edit_bot_settings(update, context): value = config_dict[data[2]] if len(str(value)) > 200: query.answer() - filename = f"{data[2]}.txt" - with open(filename, 'w', encoding='utf-8') as f: - f.write(f'{value}') - sendFile(context.bot, message, filename) + fileName = f"{data[2]}.txt" + sendFile(context.bot, message, value, fileName) return elif value == '': value = None diff --git a/bot/modules/clone.py b/bot/modules/clone.py index 1d03f771290..bf5d23e3c4f 100644 --- a/bot/modules/clone.py +++ b/bot/modules/clone.py @@ -14,6 +14,9 @@ def _clone(message, bot): + if not config_dict['GDRIVE_ID']: + sendMessage('GDRIVE_ID not Provided!', bot, message) + return args = message.text.split() reply_to = message.reply_to_message link = '' @@ -34,26 +37,35 @@ def _clone(message, bot): tag = f"@{reply_to.from_user.username}" else: tag = reply_to.from_user.mention_html(reply_to.from_user.first_name) + + def __run_multi(): + if multi > 1: + sleep(4) + nextmsg = type('nextmsg', (object, ), {'chat_id': message.chat_id, + 'message_id': message.reply_to_message.message_id + 1}) + cmsg = message.text.split() + cmsg[1] = f"{multi - 1}" + nextmsg = sendMessage(" ".join(cmsg), bot, nextmsg) + nextmsg.from_user.id = message.from_user.id + sleep(4) + Thread(target=_clone, args=(nextmsg, bot)).start() + if is_gdrive_link(link): gd = GoogleDriveHelper() res, size, name, files = gd.helper(link) if res != "": - return sendMessage(res, bot, message) + sendMessage(res, bot, message) + __run_multi() + return if config_dict['STOP_DUPLICATE']: LOGGER.info('Checking File/Folder if already in Drive...') smsg, button = gd.drive_list(name, True, True) if smsg: msg = "File/Folder is already available in Drive.\nHere are the search results:" - return sendMessage(msg, bot, message, button) - if multi > 1: - sleep(4) - nextmsg = type('nextmsg', (object, ), {'chat_id': message.chat_id, 'message_id': message.reply_to_message.message_id + 1}) - cmsg = message.text.split() - cmsg[1] = f"{multi - 1}" - nextmsg = sendMessage(" ".join(cmsg), bot, nextmsg) - nextmsg.from_user.id = message.from_user.id - sleep(4) - Thread(target=_clone, args=(nextmsg, bot)).start() + sendMessage(msg, bot, message, button) + __run_multi() + return + __run_multi() if files <= 20: msg = sendMessage(f"Cloning: {link}", bot, message) result, button = gd.clone(link) diff --git a/bot/modules/listener.py b/bot/modules/listener.py index 37efaac0177..b4534234494 100644 --- a/bot/modules/listener.py +++ b/bot/modules/listener.py @@ -69,7 +69,7 @@ def onDownloadComplete(self): if self.uid in non_queued_dl: non_queued_dl.remove(self.uid) start_from_queued() - user_dict = user_data.get(self.message.from_user.id, False) + user_dict = user_data.get(self.message.from_user.id, {}) if self.isZip: if self.seed and self.isLeech: self.newDir = f"{self.dir}10000" @@ -78,7 +78,7 @@ def onDownloadComplete(self): path = f"{m_path}.zip" with download_dict_lock: download_dict[self.uid] = ZipStatus(name, size, gid, self) - LEECH_SPLIT_SIZE = user_dict and user_dict.get('split_size') or config_dict['LEECH_SPLIT_SIZE'] + LEECH_SPLIT_SIZE = user_dict.get('split_size') or config_dict['LEECH_SPLIT_SIZE'] if self.pswd is not None: if self.isLeech and int(size) > LEECH_SPLIT_SIZE: LOGGER.info(f'Zip: orig_path: {m_path}, zip_path: {path}.0*') @@ -167,7 +167,7 @@ def onDownloadComplete(self): o_files = [] if not self.isZip: checked = False - LEECH_SPLIT_SIZE = user_dict and user_dict.get('split_size') or config_dict['LEECH_SPLIT_SIZE'] + LEECH_SPLIT_SIZE = user_dict.get('split_size') or config_dict['LEECH_SPLIT_SIZE'] for dirpath, subdir, files in walk(up_dir, topdown=False): for file_ in files: f_path = ospath.join(dirpath, file_) diff --git a/bot/modules/mirror_leech.py b/bot/modules/mirror_leech.py index 0d2c3fd13ba..a49090a0a13 100644 --- a/bot/modules/mirror_leech.py +++ b/bot/modules/mirror_leech.py @@ -22,6 +22,9 @@ def _mirror_leech(bot, message, isZip=False, extract=False, isQbit=False, isLeech=False): + if not isLeech and not config_dict['GDRIVE_ID']: + sendMessage('GDRIVE_ID not Provided!', bot, message) + return mesg = message.text.split('\n') message_args = mesg[0].split(maxsplit=1) index = 1 @@ -61,6 +64,18 @@ def _mirror_leech(bot, message, isZip=False, extract=False, isQbit=False, isLeec if link.startswith(("|", "pswd:")): link = '' + def __run_multi(): + if multi > 1: + sleep(4) + nextmsg = type('nextmsg', (object, ), {'chat_id': message.chat_id, + 'message_id': message.reply_to_message.message_id + 1}) + msg = message.text.split(maxsplit=mi+1) + msg[mi] = f"{multi - 1}" + nextmsg = sendMessage(" ".join(msg), bot, nextmsg) + nextmsg.from_user.id = message.from_user.id + sleep(4) + Thread(target=_mirror_leech, args=(bot, nextmsg, isZip, extract, isQbit, isLeech)).start() + name = mesg[0].split('|', maxsplit=1) if len(name) > 1: if 'pswd:' in name[0]: @@ -100,15 +115,7 @@ def _mirror_leech(bot, message, isZip=False, extract=False, isQbit=False, isLeec elif not isQbit and file_.mime_type != "application/x-bittorrent": listener = MirrorLeechListener(bot, message, isZip, extract, isQbit, isLeech, pswd, tag) Thread(target=TelegramDownloadHelper(listener).add_download, args=(message, f'{DOWNLOAD_DIR}{listener.uid}/', name)).start() - if multi > 1: - sleep(4) - nextmsg = type('nextmsg', (object, ), {'chat_id': message.chat_id, 'message_id': message.reply_to_message.message_id + 1}) - msg = message.text.split(maxsplit=mi+1) - msg[mi] = f"{multi - 1}" - nextmsg = sendMessage(" ".join(msg), bot, nextmsg) - nextmsg.from_user.id = message.from_user.id - sleep(4) - Thread(target=_mirror_leech, args=(bot, nextmsg, isZip, extract, isQbit, isLeech)).start() + __run_multi() return else: link = file_.get_file().file_path @@ -144,7 +151,8 @@ def _mirror_leech(bot, message, isZip=False, extract=False, isQbit=False, isLeec 3. You can add those options d, s and multi randomly. Ex: /cmd d:1:20 s 10 or /cmd s 10 d:0.5:100 4. Commands that start with qb are ONLY for torrents. ''' - return sendMessage(help_msg, bot, message) + sendMessage(help_msg, bot, message) + return LOGGER.info(link) @@ -158,7 +166,9 @@ def _mirror_leech(bot, message, isZip=False, extract=False, isQbit=False, isLeec except DirectDownloadLinkException as e: LOGGER.info(str(e)) if str(e).startswith('ERROR:'): - return sendMessage(str(e), bot, message) + sendMessage(str(e), bot, message) + __run_multi() + return elif isQbit and not is_magnet(link): if link.endswith('.torrent') or "https://api.telegram.org/file/" in link: content_type = None @@ -173,17 +183,23 @@ def _mirror_leech(bot, message, isZip=False, extract=False, isQbit=False, isLeec t.write(resp.content) link = str(file_name) else: - return sendMessage(f"{tag} ERROR: link got HTTP response: {resp.status_code}", bot, message) + sendMessage(f"{tag} ERROR: link got HTTP response: {resp.status_code}", bot, message) + __run_multi() + return except Exception as e: error = str(e).replace('<', ' ').replace('>', ' ') if error.startswith('No connection adapters were found for'): link = error.split("'")[1] else: LOGGER.error(str(e)) - return sendMessage(tag + " " + error, bot, message) + sendMessage(tag + " " + error, bot, message) + __run_multi() + return else: msg = "Qb commands for torrents only. if you are trying to dowload torrent then report." - return sendMessage(msg, bot, message) + sendMessage(msg, bot, message) + __run_multi() + return listener = MirrorLeechListener(bot, message, isZip, extract, isQbit, isLeech, pswd, tag, select, seed) @@ -213,17 +229,7 @@ def _mirror_leech(bot, message, isZip=False, extract=False, isQbit=False, isLeec auth = '' Thread(target=add_aria2c_download, args=(link, f'{DOWNLOAD_DIR}{listener.uid}', listener, name, auth, ratio, seed_time)).start() - - if multi > 1: - sleep(4) - nextmsg = type('nextmsg', (object, ), {'chat_id': message.chat_id, 'message_id': message.reply_to_message.message_id + 1}) - msg = message.text.split(maxsplit=mi+1) - msg[mi] = f"{multi - 1}" - nextmsg = sendMessage(" ".join(msg), bot, nextmsg) - nextmsg.from_user.id = message.from_user.id - sleep(4) - Thread(target=_mirror_leech, args=(bot, nextmsg, isZip, extract, isQbit, isLeech)).start() - + __run_multi() def mirror(update, context): _mirror_leech(context.bot, update.message) diff --git a/bot/modules/users_settings.py b/bot/modules/users_settings.py index c995aba943a..dd5d992d77b 100644 --- a/bot/modules/users_settings.py +++ b/bot/modules/users_settings.py @@ -6,7 +6,7 @@ from html import escape from bot import user_data, dispatcher, config_dict, DATABASE_URL, IS_PREMIUM_USER, MAX_SPLIT_SIZE -from bot.helper.telegram_helper.message_utils import sendMessage, editMessage, sendPhoto +from bot.helper.telegram_helper.message_utils import sendMessage, editMessage, sendPhoto, sendFile from bot.helper.telegram_helper.filters import CustomFilters from bot.helper.telegram_helper.bot_commands import BotCommands from bot.helper.telegram_helper.button_build import ButtonMaker @@ -20,8 +20,9 @@ def get_user_settings(from_user): name = from_user.full_name buttons = ButtonMaker() thumbpath = f"Thumbnails/{user_id}.jpg" - user_dict = user_data.get(user_id, False) - if not user_dict and config_dict['AS_DOCUMENT'] or user_dict and user_dict.get('as_doc'): + user_dict = user_data.get(user_id, {}) + AD = config_dict['AS_DOCUMENT'] + if not user_dict and AD or user_dict.get('as_doc') or 'as_doc' not in user_dict and AD: ltype = "DOCUMENT" buttons.sbutton("Send As Media", f"userset {user_id} med") else: @@ -29,26 +30,31 @@ def get_user_settings(from_user): buttons.sbutton("Send As Document", f"userset {user_id} doc") buttons.sbutton("Leech Splits", f"userset {user_id} lss") - if user_dict and user_dict.get('split_size'): + if user_dict.get('split_size'): split_size = user_dict['split_size'] else: split_size = config_dict['LEECH_SPLIT_SIZE'] - if not user_dict and config_dict['EQUAL_SPLITS'] or user_dict and user_dict.get('equal_splits'): + ES = config_dict['EQUAL_SPLITS'] + if not user_dict and ES or user_dict.get('equal_splits') or 'equal_splits' not in user_dict and ES: equal_splits = 'Enabled' else: equal_splits = 'Disabled' - if not user_dict and config_dict['MEDIA_GROUP'] or user_dict and user_dict.get('media_group'): + MG = config_dict['MEDIA_GROUP'] + if not user_dict and MG or user_dict.get('media_group') or 'media_group' not in user_dict and MG: media_group = 'Enabled' + buttons.sbutton("Disable Media Group", f"userset {user_id} mgroup") else: media_group = 'Disabled' + buttons.sbutton("Enable Media Group", f"userset {user_id} mgroup") buttons.sbutton("YT-DLP Quality", f"userset {user_id} ytq") - if user_dict and user_dict.get('yt_ql'): + YQ = config_dict['YT_DLP_QUALITY'] + if user_dict.get('yt_ql'): ytq = user_dict['yt_ql'] - elif config_dict['YT_DLP_QUALITY']: - ytq = config_dict['YT_DLP_QUALITY'] + elif not user_dict and YQ or 'yt_ql' not in user_dict and YQ: + ytq = YQ else: ytq = 'None' @@ -120,7 +126,7 @@ def edit_user_settings(update, context): data = query.data data = data.split() thumb_path = f"Thumbnails/{user_id}.jpg" - user_dict = user_data.get(user_id, False) + user_dict = user_data.get(user_id, {}) if user_id != int(data[1]): query.answer(text="Not Yours!", show_alert=True) elif data[2] == "doc": @@ -185,7 +191,7 @@ def edit_user_settings(update, context): handler_dict[user_id] = True buttons = ButtonMaker() buttons.sbutton("Back", f"userset {user_id} back") - if user_dict and user_dict.get('yt_ql'): + if user_dict.get('yt_ql'): buttons.sbutton("Remove YT-DLP Quality", f"userset {user_id} rytq", 'header') buttons.sbutton("Close", f"userset {user_id} close") rmsg = f''' @@ -220,16 +226,12 @@ def edit_user_settings(update, context): start_time = time() handler_dict[user_id] = True buttons = ButtonMaker() - if user_dict and user_dict.get('split_size'): + if user_dict.get('split_size'): buttons.sbutton("Reset Split Size", f"userset {user_id} rlss") - if not user_dict and config_dict['EQUAL_SPLITS'] or user_dict and user_dict.get('equal_splits'): + if not user_dict and config_dict['EQUAL_SPLITS'] or user_dict.get('equal_splits'): buttons.sbutton("Disable Equal Splits", f"userset {user_id} esplits") else: buttons.sbutton("Enable Equal Splits", f"userset {user_id} esplits") - if not user_dict and config_dict['MEDIA_GROUP'] or user_dict and user_dict.get('media_group'): - buttons.sbutton("Disable Media Group", f"userset {user_id} mgroup") - else: - buttons.sbutton("Enable Media Group", f"userset {user_id} mgroup") buttons.sbutton("Back", f"userset {user_id} back") buttons.sbutton("Close", f"userset {user_id} close") editMessage(f'Send Leech split size in bytes. IS_PREMIUM_USER: {IS_PREMIUM_USER}. Timeout: 60 sec', message, buttons.build_menu(1)) @@ -252,14 +254,13 @@ def edit_user_settings(update, context): elif data[2] == 'esplits': query.answer() handler_dict[user_id] = False - update_user_ldata(user_id, 'equal_splits', not bool(user_dict and user_dict.get('equal_splits'))) + update_user_ldata(user_id, 'equal_splits', not bool(user_dict.get('equal_splits'))) update_user_settings(message, query.from_user) if DATABASE_URL: DbManger().update_user_data(user_id) elif data[2] == 'mgroup': query.answer() - handler_dict[user_id] = False - update_user_ldata(user_id, 'media_group', not bool(user_dict and user_dict.get('media_group'))) + update_user_ldata(user_id, 'media_group', not bool(user_dict.get('media_group'))) update_user_settings(message, query.from_user) if DATABASE_URL: DbManger().update_user_data(user_id) @@ -276,7 +277,10 @@ def edit_user_settings(update, context): def send_users_settings(update, context): msg = ''.join(f'{u}: {escape(str(d))}\n\n' for u, d in user_data.items()) if msg: - sendMessage(msg, context.bot, update.message) + if len(msg.encode()) > 4000: + sendFile(context.bot, update.message, msg, 'users_settings.txt') + else: + sendMessage(msg, context.bot, update.message) else: sendMessage('No users data!', context.bot, update.message) diff --git a/bot/modules/ytdlp.py b/bot/modules/ytdlp.py index e6215e44beb..4c0371550a4 100644 --- a/bot/modules/ytdlp.py +++ b/bot/modules/ytdlp.py @@ -15,6 +15,9 @@ listener_dict = {} def _ytdl(bot, message, isZip=False, isLeech=False): + if not isLeech and not config_dict['GDRIVE_ID']: + sendMessage('GDRIVE_ID not Provided!', bot, message) + return mssg = message.text user_id = message.from_user.id msg_id = message.message_id @@ -46,6 +49,18 @@ def _ytdl(bot, message, isZip=False, isLeech=False): link = re_split(r"opt:|pswd:|\|", link)[0] link = link.strip() + def __run_multi(): + if multi > 1: + sleep(4) + nextmsg = type('nextmsg', (object, ), {'chat_id': message.chat_id, + 'message_id': message.reply_to_message.message_id + 1}) + ymsg = mssg.split(maxsplit=mi+1) + ymsg[mi] = f"{multi - 1}" + nextmsg = sendMessage(" ".join(ymsg), bot, nextmsg) + nextmsg.from_user.id = message.from_user.id + sleep(4) + Thread(target=_ytdl, args=(bot, nextmsg, isZip, isLeech)).start() + name = mssg.split('|', maxsplit=1) if len(name) > 1: if 'opt:' in name[0] or 'pswd:' in name[0]: @@ -114,18 +129,21 @@ def _ytdl(bot, message, isZip=False, isLeech=False): result = ydl.extractMetaData(link, name, opt, True) except Exception as e: msg = str(e).replace('<', ' ').replace('>', ' ') - return sendMessage(tag + " " + msg, bot, message) + sendMessage(tag + " " + msg, bot, message) + __run_multi() + return if not select: - user_dict = user_data.get(user_id, False) + YTQ = config_dict['YT_DLP_QUALITY'] + user_dict = user_data.get(user_id, {}) if 'format:' in opt: opts = opt.split('|') for f in opts: if f.startswith('format:'): qual = f.split('format:', 1)[1] - elif user_dict and user_dict.get('yt_ql', False): + elif user_dict.get('yt_ql'): qual = user_dict['yt_ql'] - elif config_dict['YT_DLP_QUALITY']: - qual = config_dict['YT_DLP_QUALITY'] + elif not user_dict and YTQ or 'yt_ql' not in user_dict and YTQ: + qual = YTQ if qual: playlist = 'entries' in result LOGGER.info(f"Downloading with YT-DLP: {link}") @@ -209,15 +227,7 @@ def _ytdl(bot, message, isZip=False, isLeech=False): Thread(target=_auto_cancel, args=(bmsg, msg_id)).start() - if multi > 1: - sleep(4) - nextmsg = type('nextmsg', (object, ), {'chat_id': message.chat_id, 'message_id': message.reply_to_message.message_id + 1}) - ymsg = mssg.split(maxsplit=mi+1) - ymsg[mi] = f"{multi - 1}" - nextmsg = sendMessage(" ".join(ymsg), bot, nextmsg) - nextmsg.from_user.id = message.from_user.id - sleep(4) - Thread(target=_ytdl, args=(bot, nextmsg, isZip, isLeech)).start() + __run_multi() def _qual_subbuttons(task_id, b_name, msg): buttons = ButtonMaker()