Skip to content

Commit

Permalink
Add screenshot feature
Browse files Browse the repository at this point in the history
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 anasty17#1521

Signed-off-by: anasty17 <e.anastayyar@gmail.com>
  • Loading branch information
anasty17 committed Nov 15, 2023
1 parent e4775f5 commit 5db0f6b
Show file tree
Hide file tree
Showing 12 changed files with 132 additions and 56 deletions.
4 changes: 2 additions & 2 deletions bot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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

Expand Down
56 changes: 31 additions & 25 deletions bot/helper/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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]
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion bot/helper/ext_utils/bot_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions bot/helper/ext_utils/help_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@
/cmd -sv (it will take the default values which 60sec sample duration and part duration is 4sec).<br>
You can control those values. Example: /cmd -sv 70:5(sample-duration:part-duration) or /cmd -sv :5 or /cmd -sv 70.<br>
<br>
<b>SreensShots</b>: -ss<br>
Create up to 10 screenshots for one video or folder of vidoes.<br>
/cmd -ss (it will take the default values which is 10 photos).<br>
You can control this value. Example: /cmd -ss 6.<br>
<br>
Check here all supported <a href='https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md'>SITES</a><br>
Check all yt-dlp api options from this <a href='https://github.com/yt-dlp/yt-dlp/blob/master/yt_dlp/YoutubeDL.py#L184'>FILE</a> or use this <a href='https://t.me/mltb_official_channel/177'>script</a> to convert cli arguments to api options.<br>
"""
Expand Down Expand Up @@ -173,6 +178,11 @@
/cmd -sv (it will take the default values which 60sec sample duration and part duration is 4sec).<br>
You can control those values. Example: /cmd -sv 70:5(sample-duration:part-duration) or /cmd -sv :5 or /cmd -sv 70.<br>
<br>
<b>SreensShots</b>: -ss<br>
Create up to 10 screenshots for one video or folder of vidoes.<br>
/cmd -ss (it will take the default values which is 10 photos).<br>
You can control this value. Example: /cmd -ss 6.<br>
<br>
<b>NOTES:</b><br>
1. Commands that start with <b>qb</b> are ONLY for torrents.
"""
Expand Down
37 changes: 35 additions & 2 deletions bot/helper/ext_utils/media_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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)
Expand Down Expand Up @@ -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]
Expand Down
8 changes: 4 additions & 4 deletions bot/helper/ext_utils/status_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"<b>CPU:</b> {cpu_percent()}% | <b>FREE:</b> {get_readable_file_size(disk_usage(DOWNLOAD_DIR).free)}"
Expand Down
57 changes: 40 additions & 17 deletions bot/helper/mirror_utils/telegram_uploader.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -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

Expand All @@ -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:
Expand All @@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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
)
Expand All @@ -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(
Expand All @@ -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
Expand Down Expand Up @@ -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!")
6 changes: 3 additions & 3 deletions bot/modules/clone.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
2 changes: 2 additions & 0 deletions bot/modules/mirror_leech.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ async def newEvent(self):
"-e": False,
"-z": False,
"-sv": False,
"-ss": False,
"-i": 0,
"-sp": 0,
"link": "",
Expand Down Expand Up @@ -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"]
Expand Down
Loading

0 comments on commit 5db0f6b

Please sign in to comment.