From 5db0f6b651f68b91a6491eb123b372e286e92d9a Mon Sep 17 00:00:00 2001 From: anasty17 Date: Wed, 15 Nov 2023 03:05:47 +0200 Subject: [PATCH] Add screenshot feature Fix: sample video args Changes: when leeching as doc, videos will be splited by split and not with ffmpeg so later u can join them again. ONLY IF LEECHNG AS DOC I will try to edit the sample video function to make it faster! close #1521 Signed-off-by: anasty17 --- bot/__init__.py | 4 +- bot/helper/common.py | 56 ++++++++++--------- bot/helper/ext_utils/bot_utils.py | 2 +- bot/helper/ext_utils/help_messages.py | 10 ++++ bot/helper/ext_utils/media_utils.py | 37 ++++++++++++- bot/helper/ext_utils/status_utils.py | 8 +-- bot/helper/mirror_utils/telegram_uploader.py | 57 ++++++++++++++------ bot/modules/clone.py | 6 +-- bot/modules/mirror_leech.py | 2 + bot/modules/rss.py | 2 +- bot/modules/status.py | 2 +- bot/modules/ytdlp.py | 2 + 12 files changed, 132 insertions(+), 56 deletions(-) diff --git a/bot/__init__.py b/bot/__init__.py index 210e1522175..aee06bae824 100644 --- a/bot/__init__.py +++ b/bot/__init__.py @@ -200,7 +200,7 @@ TELEGRAM_HASH, session_string=USER_SESSION_STRING, parse_mode=enums.ParseMode.HTML, - max_concurrent_transmissions=1000, + max_concurrent_transmissions=10, ).start() IS_PREMIUM_USER = user.me.is_premium else: @@ -528,7 +528,7 @@ def aria2c_init(): bot_token=BOT_TOKEN, workers=1000, parse_mode=enums.ParseMode.HTML, - max_concurrent_transmissions=1000, + max_concurrent_transmissions=10, ).start() bot_loop = bot.loop diff --git a/bot/helper/common.py b/bot/helper/common.py index 5374ad3a4fa..235f13fb3d5 100644 --- a/bot/helper/common.py +++ b/bot/helper/common.py @@ -72,7 +72,6 @@ def __init__(self, message): self.name = "" self.session = "" self.newDir = "" - self.sampleVideo = "" self.multiTag = 0 self.splitSize = 0 self.maxSplitSize = 0 @@ -92,6 +91,9 @@ def __init__(self, message): self.isYtDlp = False self.privateLink = False self.stopDuplicate = False + self.sampleVideo = False + self.screenShots = False + self.as_doc = False self.suproc = None self.client = None self.thumb = None @@ -218,6 +220,27 @@ async def beforeStart(self): ) != self.getConfigPath(self.upDest): raise ValueError("You must use the same config to clone!") else: + if self.upDest: + if self.userTransmission: + chat = await user.get_chat(self.upDest) + uploader_id = user.me.id + else: + chat = await self.client.get_chat(self.upDest) + uploader_id = self.client.me.id + if chat.type.name not in ["SUPERGROUP", "CHANNEL"]: + raise ValueError( + "Custom Leech Destination only allowed for super-group or channel!" + ) + member = await chat.get_member(uploader_id) + if ( + not member.privileges.can_manage_chat + or not member.privileges.can_delete_messages + ): + raise ValueError("You don't have enough privileges in this chat!") + elif self.userTransmission and not self.isSuperChat: + raise ValueError( + "Use SuperGroup incase you want to upload using User session!" + ) if self.splitSize: if self.splitSize.isdigit(): self.splitSize = int(self.splitSize) @@ -254,27 +277,10 @@ async def beforeStart(self): self.userTransmission = IS_PREMIUM_USER if self.upDest.isdigit() or self.upDest.startswith("-"): self.upDest = int(self.upDest) - if self.upDest: - if self.userTransmission: - chat = await user.get_chat(self.upDest) - uploader_id = user.me.id - else: - chat = await self.client.get_chat(self.upDest) - uploader_id = self.client.me.id - if chat.type.name not in ["SUPERGROUP", "CHANNEL"]: - raise ValueError( - "Custom Leech Destination only allowed for super-group or channel!" - ) - member = await chat.get_member(uploader_id) - if ( - not member.privileges.can_manage_chat - or not member.privileges.can_delete_messages - ): - raise ValueError("You don't have enough privileges in this chat!") - elif self.userTransmission and not self.isSuperChat: - raise ValueError( - "Use SuperGroup incase you want to upload using User session!" - ) + + self.as_doc = self.user_dict.get("as_doc", False) or ( + config_dict["AS_DOCUMENT"] if "as_doc" not in self.user_dict else False + ) if is_telegram_link(self.thumb): msg = (await get_tg_link_message(self.thumb))[0] @@ -295,7 +301,7 @@ async def getTag(self, text: list): @new_task async def run_multi(self, input_list, folder_name, obj): - await sleep(5) + await sleep(7) if not self.multiTag and self.multi > 1: self.multiTag = token_urlsafe(3) multi_tags.add(self.multiTag) @@ -585,8 +591,8 @@ async def proceedSplit(self, up_dir, m_size, o_files, size, gid): async def generateSampleVideo(self, dl_path, size, gid): data = self.sampleVideo.split(":") if isinstance(self.sampleVideo, str) else "" if data: - sample_duration = data[0] if data[0] else 60 - part_duration = data[1] if len(data) > 1 else 4 + sample_duration = int(data[0]) if data[0] else 60 + part_duration = int(data[1]) if len(data) > 1 else 4 else: sample_duration = 60 part_duration = 4 diff --git a/bot/helper/ext_utils/bot_utils.py b/bot/helper/ext_utils/bot_utils.py index 652e1999682..0097fd49531 100644 --- a/bot/helper/ext_utils/bot_utils.py +++ b/bot/helper/ext_utils/bot_utils.py @@ -94,7 +94,7 @@ async def get_telegraph_list(telegraph_content): def arg_parser(items, arg_base): if not items: return arg_base - bool_arg_set = {"-b", "-e", "-z", "-s", "-j", "-d", "-sv"} + bool_arg_set = {"-b", "-e", "-z", "-s", "-j", "-d", "-sv", "-ss"} t = len(items) i = 0 arg_start = -1 diff --git a/bot/helper/ext_utils/help_messages.py b/bot/helper/ext_utils/help_messages.py index 87f7140f031..1bf066c98e0 100644 --- a/bot/helper/ext_utils/help_messages.py +++ b/bot/helper/ext_utils/help_messages.py @@ -67,6 +67,11 @@ /cmd -sv (it will take the default values which 60sec sample duration and part duration is 4sec).
You can control those values. Example: /cmd -sv 70:5(sample-duration:part-duration) or /cmd -sv :5 or /cmd -sv 70.

+SreensShots: -ss
+Create up to 10 screenshots for one video or folder of vidoes.
+/cmd -ss (it will take the default values which is 10 photos).
+You can control this value. Example: /cmd -ss 6.
+
Check here all supported SITES
Check all yt-dlp api options from this FILE or use this script to convert cli arguments to api options.
""" @@ -173,6 +178,11 @@ /cmd -sv (it will take the default values which 60sec sample duration and part duration is 4sec).
You can control those values. Example: /cmd -sv 70:5(sample-duration:part-duration) or /cmd -sv :5 or /cmd -sv 70.

+SreensShots: -ss
+Create up to 10 screenshots for one video or folder of vidoes.
+/cmd -ss (it will take the default values which is 10 photos).
+You can control this value. Example: /cmd -ss 6.
+
NOTES:
1. Commands that start with qb are ONLY for torrents. """ diff --git a/bot/helper/ext_utils/media_utils.py b/bot/helper/ext_utils/media_utils.py index 2c91ffcabf4..bc6d8a67558 100644 --- a/bot/helper/ext_utils/media_utils.py +++ b/bot/helper/ext_utils/media_utils.py @@ -148,6 +148,39 @@ async def get_document_type(path): return is_video, is_audio, is_image +async def take_ss(video_file, ss_nb) -> list: + if ss_nb > 10: + ss_nb = 10 + duration = (await get_media_info(video_file))[0] + if duration != 0: + dirpath, name = video_file.rsplit("/", 1) + name = name.rsplit(".", 1)[0] + dirpath = f"{dirpath}/screenshots/" + if not await aiopath.exists(dirpath): + await mkdir(dirpath) + interval = duration // ss_nb + 1 + cap_time = interval + outputs = [] + cmd = '' + for i in range(ss_nb): + output = f"{dirpath}SS.{name}_{i:02}.png" + outputs.append(output) + cmd += f'ffmpeg -hide_banner -loglevel error -ss {cap_time} -i "{video_file}" -q:v 1 -frames:v 1 "{output}"' + cap_time += interval + if i + 1 != ss_nb: + cmd += ' && ' + _, err, code = await cmd_exec(cmd, True) + if code != 0: + LOGGER.error( + f"Error while creating sreenshots from video. Path: {video_file} stderr: {err}" + ) + return [] + return outputs + else: + LOGGER.error("take_ss: Can't get the duration of video") + return [] + + async def get_audio_thumb(audio_file): des_dir = "Thumbnails/" if not await aiopath.exists(des_dir): @@ -174,7 +207,7 @@ async def get_audio_thumb(audio_file): return des_dir -async def take_ss(video_file, duration): +async def create_thumbnail(video_file, duration): des_dir = "Thumbnails" if not await aiopath.exists(des_dir): await mkdir(des_dir) @@ -233,7 +266,7 @@ async def split_file( parts = -(-size // listener.splitSize) if listener.equalSplits and not inLoop: split_size = (size // parts) + (size % parts) - if (await get_document_type(path))[0]: + if not listener.as_doc and (await get_document_type(path))[0]: if multi_streams: multi_streams = await is_multi_streams(path) duration = (await get_media_info(path))[0] diff --git a/bot/helper/ext_utils/status_utils.py b/bot/helper/ext_utils/status_utils.py index 29ad563a6b9..9700adbb325 100644 --- a/bot/helper/ext_utils/status_utils.py +++ b/bot/helper/ext_utils/status_utils.py @@ -173,10 +173,10 @@ def get_readable_message(sid, is_user, page_no=1, status="All", page_step=1): if tasks_no > 30: for i in [1, 2, 4, 6, 8, 10, 15, 20]: buttons.ibutton(i, f"status {sid} ps {i}", position="footer") - if len(task_dict) > STATUS_LIMIT or status != "All": - for label, status_value in STATUS_VALUES: - if status_value != status: - buttons.ibutton(label, f"status {sid} st {status_value}") + if len(task_dict) > STATUS_LIMIT or status != "All": + for label, status_value in STATUS_VALUES: + if status_value != status: + buttons.ibutton(label, f"status {sid} st {status_value}") buttons.ibutton("♻️", f"status {sid} ref", position="header") button = buttons.build_menu(8) msg += f"CPU: {cpu_percent()}% | FREE: {get_readable_file_size(disk_usage(DOWNLOAD_DIR).free)}" diff --git a/bot/helper/mirror_utils/telegram_uploader.py b/bot/helper/mirror_utils/telegram_uploader.py index d62acd9ed32..80925b1cece 100644 --- a/bot/helper/mirror_utils/telegram_uploader.py +++ b/bot/helper/mirror_utils/telegram_uploader.py @@ -8,7 +8,7 @@ from os import walk, path as ospath from time import time from PIL import Image -from pyrogram.types import InputMediaVideo, InputMediaDocument +from pyrogram.types import InputMediaVideo, InputMediaDocument, InputMediaPhoto from pyrogram.errors import FloodWait, RPCError from asyncio import sleep from tenacity import ( @@ -28,8 +28,9 @@ from bot.helper.ext_utils.media_utils import ( get_media_info, get_document_type, - take_ss, + create_thumbnail, get_audio_thumb, + take_ss, ) from bot.helper.telegram_helper.message_utils import deleteMessage @@ -53,9 +54,7 @@ def __init__(self, listener, path): self._last_msg_in_group = False self._up_path = "" self._lprefix = "" - self._as_doc = False self._media_group = False - self.name = self._listener.name async def _upload_progress(self, current, total): if self._is_cancelled: @@ -68,11 +67,6 @@ async def _upload_progress(self, current, total): self._processed_bytes += chunk_size async def _user_settings(self): - self._as_doc = self._listener.user_dict.get("as_doc", False) or ( - config_dict["AS_DOCUMENT"] - if "as_doc" not in self._listener.user_dict - else False - ) self._media_group = self._listener.user_dict.get("media_group") or ( config_dict["MEDIA_GROUP"] if "media_group" not in self._listener.user_dict @@ -98,14 +92,14 @@ async def _msg_to_reply(self): self._sent_msg = await user.send_message( chat_id=self._listener.upDest, text=msg, - disable_web_page_preview=False, + disable_web_page_preview=True, disable_notification=True, ) else: self._sent_msg = await self._listener.client.send_message( chat_id=self._listener.upDest, text=msg, - disable_web_page_preview=False, + disable_web_page_preview=True, disable_notification=True, ) except Exception as e: @@ -183,6 +177,29 @@ def _get_input_media(self, subkey, key): rlist.append(input_media) return rlist + async def _send_screenshots(self): + if isinstance(self._listener.screenShots, str): + ss_nb = int(self._listener.screenShots) + else: + ss_nb = 10 + outputs = await take_ss(self._up_path, ss_nb) + inputs = [] + if outputs: + for m in outputs: + if await aiopath.exists(m): + cap = m.rsplit("/", 1)[-1] + inputs.append(InputMediaPhoto(m, cap)) + else: + outputs.remove(m) + if outputs: + self._sent_msg = (await self._sent_msg.reply_media_group( + media=inputs, + quote=True, + disable_notification=True, + ))[-1] + for m in outputs: + await aioremove(m) + async def _send_media_group(self, subkey, key, msgs): msgs_list = await msgs[0].reply_to_message.reply_media_group( media=self._get_input_media(subkey, key), @@ -297,7 +314,7 @@ async def upload(self, o_files, m_size, size): "Files Corrupted or unable to upload. Check logs!" ) return - LOGGER.info(f"Leech Completed: {self.name}") + LOGGER.info(f"Leech Completed: {self._listener.name}") await self._listener.onUploadComplete( None, size, self._msgs_dict, self._total_files, self._corrupted ) @@ -324,13 +341,17 @@ async def _upload_file(self, cap_mono, file, force_document=False): thumb = await get_audio_thumb(self._up_path) if ( - self._as_doc + self._listener.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 = await take_ss(self._up_path, None) + if is_video: + if self._listener.screenShots: + await self._send_screenshots() + if thumb is None: + thumb = await create_thumbnail(self._up_path, None) + if self._is_cancelled: return self._sent_msg = await self._sent_msg.reply_document( @@ -343,10 +364,12 @@ async def _upload_file(self, cap_mono, file, force_document=False): progress=self._upload_progress, ) elif is_video: + if self._listener.screenShots: + await self._send_screenshots() key = "videos" duration = (await get_media_info(self._up_path))[0] if thumb is None: - thumb = await take_ss(self._up_path, duration) + thumb = await create_thumbnail(self._up_path, duration) if thumb is not None: with Image.open(thumb) as img: width, height = img.size @@ -468,5 +491,5 @@ def processed_bytes(self): async def cancel_task(self): self._is_cancelled = True - LOGGER.info(f"Cancelling Upload: {self.name}") + LOGGER.info(f"Cancelling Upload: {self._listener.name}") await self._listener.onUploadError("your upload has been stopped!") diff --git a/bot/modules/clone.py b/bot/modules/clone.py index 9d7cf54e982..561036552ce 100644 --- a/bot/modules/clone.py +++ b/bot/modules/clone.py @@ -106,15 +106,15 @@ async def newEvent(self): self.run_multi(input_list, "", Clone) if len(self.link) == 0: - await sendMessage(self.message, "Open this link for usage help!", COMMAND_USAGE["clone"]) + await sendMessage( + self.message, "Open this link for usage help!", COMMAND_USAGE["clone"] + ) return - try: await self.beforeStart() except Exception as e: await sendMessage(self.message, e) return - await self._proceedToClone() async def _proceedToClone(self): diff --git a/bot/modules/mirror_leech.py b/bot/modules/mirror_leech.py index e284a2768fa..0a65a3b6e4f 100644 --- a/bot/modules/mirror_leech.py +++ b/bot/modules/mirror_leech.py @@ -78,6 +78,7 @@ async def newEvent(self): "-e": False, "-z": False, "-sv": False, + "-ss": False, "-i": 0, "-sp": 0, "link": "", @@ -105,6 +106,7 @@ async def newEvent(self): self.thumb = args["-t"] self.splitSize = args["-sp"] self.sampleVideo = args["-sv"] + self.screenShots = args["-ss"] headers = args["-h"] isBulk = args["-b"] diff --git a/bot/modules/rss.py b/bot/modules/rss.py index 332310888d1..eee83d9784a 100644 --- a/bot/modules/rss.py +++ b/bot/modules/rss.py @@ -66,7 +66,7 @@ async def getRssMenu(_, message): await sendMessage(message, msg, button) -async def rssSub(client, message, pre_event): +async def rssSub(_, message, pre_event): user_id = message.from_user.id handler_dict[user_id] = False if username := message.from_user.username: diff --git a/bot/modules/status.py b/bot/modules/status.py index 4a4ffe97f03..122393bf3af 100644 --- a/bot/modules/status.py +++ b/bot/modules/status.py @@ -132,7 +132,7 @@ async def status_pages(_, query): msg = f"""DL: {tasks['Download']} | UP: {tasks['Upload']} | SD: {tasks['Seed']} | AR: {tasks['Archive']} EX: {tasks['Extract']} | SP: {tasks['Split']} | QD: {tasks['QueueDl']} | QU: {tasks['QueueUp']} -CL: {tasks['Clone']} | CH: {tasks['CheckUp']} | PA:{tasks['Pause']} | SV:{tasks['SamVid']} +CL: {tasks['Clone']} | CH: {tasks['CheckUp']} | PA: {tasks['Pause']} | SV: {tasks['SamVid']} ODLS: {get_readable_file_size(dl_speed)}/s OULS: {get_readable_file_size(up_speed)}/s diff --git a/bot/modules/ytdlp.py b/bot/modules/ytdlp.py index ffa4a73d738..ba13e367cb8 100644 --- a/bot/modules/ytdlp.py +++ b/bot/modules/ytdlp.py @@ -293,6 +293,7 @@ async def newEvent(self): "-b": False, "-z": False, "-sv": False, + "-ss": False, "-i": 0, "-sp": 0, "link": "", @@ -320,6 +321,7 @@ async def newEvent(self): self.thumb = args["-t"] self.splitSize = args["-sp"] self.sampleVideo = args["-sv"] + self.screenShots = args["-ss"] isBulk = args["-b"] folder_name = args["-m"]