diff --git a/README.md b/README.md
index 45e44118267b..bb189da1e3a2 100644
--- a/README.md
+++ b/README.md
@@ -383,6 +383,8 @@ programming in Python.
- `(text)` will get removed
- `[test]` will get replaced by test
- `\text\` will get replaced by text with sensitive case
+ - `METADATA_TXT`: Edit metadata of the video. `Str`
+ - `META_ATTACHMENT`: Add attachment to the metadata. `Str`
**12. Super Group Features**
diff --git a/bot/__init__.py b/bot/__init__.py
index 0ef32f14d918..ebb66518fb54 100644
--- a/bot/__init__.py
+++ b/bot/__init__.py
@@ -456,6 +456,20 @@
if len(LEECH_CAPTION_FONT) == 0:
LEECH_CAPTION_FONT = ""
+METADATA_TXT = environ.get(
+ "METADATA_TXT",
+ ""
+)
+if len(METADATA_TXT) == 0:
+ METADATA_TXT = ""
+
+META_ATTACHMENT = environ.get(
+ "META_ATTACHMENT",
+ ""
+)
+if len(META_ATTACHMENT) == 0:
+ META_ATTACHMENT = ""
+
SEARCH_PLUGINS = environ.get(
"SEARCH_PLUGINS",
""
@@ -1098,6 +1112,8 @@
"MIXED_LEECH": MIXED_LEECH,
"MEGA_LIMIT": MEGA_LIMIT,
"MINIMUM_DURATOIN": MINIMUM_DURATOIN,
+ "METADATA_TXT": METADATA_TXT,
+ "META_ATTACHMENT": META_ATTACHMENT,
"NAME_SUBSTITUTE": NAME_SUBSTITUTE,
"NZB_LIMIT": NZB_LIMIT,
"PLAYLIST_LIMIT": PLAYLIST_LIMIT,
diff --git a/bot/helper/common.py b/bot/helper/common.py
index a2881b83aba7..0fc0a9cb1924 100644
--- a/bot/helper/common.py
+++ b/bot/helper/common.py
@@ -60,8 +60,10 @@
is_telegram_link,
)
from bot.helper.ext_utils.media_utils import (
+ add_attachment,
createThumb,
createSampleVideo,
+ edit_video_metadata,
take_ss,
)
from bot.helper.ext_utils.media_utils import (
@@ -79,6 +81,7 @@
from bot.helper.task_utils.status_utils.media_convert_status import (
MediaConvertStatus,
)
+from bot.helper.task_utils.status_utils.meta_status import MetaStatus
from bot.helper.task_utils.status_utils.split_status import SplitStatus
from bot.helper.task_utils.status_utils.zip_status import ZipStatus
from bot.helper.telegram_helper.bot_commands import BotCommands
@@ -120,6 +123,8 @@ def __init__(self):
self.mode = ""
self.time = ""
self.chatId = ""
+ self.metaData = None
+ self.metaAttachment = None
self.getChat = None
self.splitSize = 0
self.maxSplitSize = 0
@@ -392,6 +397,16 @@ async def beforeStart(self):
"!qB"
]
)
+ self.metaData = self.metaData or self.userDict.get("metatxt") or (
+ config_dict["METADATA_TXT"]
+ if "metatxt" not in self.userDict
+ else False
+ )
+ self.metaAttachment = self.metaAttachment or self.userDict.get("attachmenturl") or (
+ config_dict["META_ATTACHMENT"]
+ if "attachmenturl" not in self.userDict
+ else False
+ )
if self.link not in [
"rcl",
"gdl"
@@ -1170,7 +1185,11 @@ async def proceedCompress(self, dl_path, gid, o_files, ft_delete):
async def proceedSplit(self, up_dir, m_size, o_files, gid):
checked = False
- for dirpath, _, files in await sync_to_async(
+ for (
+ dirpath,
+ _,
+ files
+ ) in await sync_to_async(
walk,
up_dir,
topdown=False
@@ -1702,3 +1721,35 @@ async def substitute(self, dl_path):
)
)
return dl_path
+
+ async def proceedMetadata(self, up_path, gid):
+ (
+ is_video,
+ _,
+ _
+ ) = await get_document_type(up_path)
+ if is_video:
+ async with task_dict_lock:
+ task_dict[self.mid] = MetaStatus(
+ self,
+ gid
+ )
+ LOGGER.info(f"Editing Metadata: {self.metaData} into {up_path}")
+ await edit_video_metadata(
+ self,
+ up_path
+ )
+ return up_path
+
+ async def proceedAttachment(self, up_path, gid):
+ async with task_dict_lock:
+ task_dict[self.mid] = MetaStatus(
+ self,
+ gid
+ )
+ LOGGER.info(f"Adding Attachment: {self.metaAttachment} into {up_path}")
+ await add_attachment(
+ self,
+ up_path
+ )
+ return up_path
diff --git a/bot/helper/ext_utils/media_utils.py b/bot/helper/ext_utils/media_utils.py
index 773b0cc8b7b7..0261701f3178 100644
--- a/bot/helper/ext_utils/media_utils.py
+++ b/bot/helper/ext_utils/media_utils.py
@@ -1,3 +1,4 @@
+from pathlib import Path
from PIL import Image
from aiofiles.os import (
remove,
@@ -165,7 +166,7 @@ async def createThumb(msg, _id=""):
await remove(photo_dir)
return des_dir
-
+global_streams = {}
async def is_multi_streams(path):
try:
result = await cmd_exec(
@@ -189,8 +190,8 @@ async def is_multi_streams(path):
):
fields = eval(result[0]).get("streams")
if fields is None:
- LOGGER.error(f"get_video_streams: {result}")
return False
+ global_streams["stream"] = fields
videos = 0
audios = 0
for stream in fields:
@@ -804,3 +805,260 @@ async def createSampleVideo(listener, video_file, sample_duration, part_duration
if await aiopath.exists(output_file):
await remove(output_file)
return False
+
+
+SUPPORTED_VIDEO_EXTENSIONS = {
+ ".mp4",
+ ".mkv"
+}
+
+
+async def edit_video_metadata(listener, dir):
+
+ data = listener.metaData
+ dir_path = Path(dir)
+
+ if dir_path.suffix.lower() not in SUPPORTED_VIDEO_EXTENSIONS:
+ return dir
+
+ file_name = dir_path.name
+ work_path = dir_path.with_suffix(".temp.mkv")
+
+ await is_multi_streams(dir)
+
+ cmd = [
+ "ffmpeg",
+ "-y",
+ "-i",
+ dir,
+ "-c",
+ "copy",
+ "-metadata",
+ f"title={data}",
+ "-threads",
+ f"{cpu_count() // 2}", # type: ignore
+ ]
+
+ meta_info = [
+ "copyright",
+ "description",
+ "license",
+ "LICENSE",
+ "author",
+ "summary",
+ "comment",
+ "artist",
+ "album",
+ "genre",
+ "date",
+ "creation_time",
+ "language",
+ "publisher",
+ "encoder",
+ "SUMMARY",
+ "AUTHOR",
+ "WEBSITE",
+ "COMMENT",
+ "ENCODER",
+ "FILENAME",
+ "MIMETYPE",
+ "PURL",
+ "ALBUM"
+ ]
+
+ for field in meta_info:
+ cmd.extend([
+ "-metadata",
+ f"{field}="
+ ])
+
+ audio_index = 0
+ subtitle_index = 0
+ first_video = False
+
+ if global_streams:
+ for stream in global_streams["stream"]:
+ stream_index = stream["index"]
+ stream_type = stream["codec_type"]
+
+ if stream_type == "video":
+ if not first_video:
+ cmd.extend([
+ "-map",
+ f"0:{stream_index}"
+ ])
+ first_video = True
+ cmd.extend([
+ f"-metadata:s:v:{stream_index}",
+ f"title={data}"
+ ])
+
+ elif stream_type == "audio":
+ cmd.extend([
+ "-map",
+ f"0:{stream_index}",
+ f"-metadata:s:a:{audio_index}",
+ f"title={data}"
+ ])
+ audio_index += 1
+
+ elif stream_type == "subtitle":
+ codec_name = stream.get(
+ "codec_name",
+ "unknown"
+ )
+ if codec_name not in [
+ "webvtt",
+ "unknown"
+ ]:
+ cmd.extend([
+ "-map", f"0:{stream_index}",
+ f"-metadata:s:s:{subtitle_index}",
+ f"title={data}"
+ ])
+ subtitle_index += 1
+ else:
+ LOGGER.info(f"Skipping unsupported subtitle metadata modification: {codec_name} for stream {stream_index}")
+
+ else:
+ cmd.extend([
+ "-map",
+ f"0:{stream_index}"
+ ])
+
+ else:
+ LOGGER.info("No streams found. Skipping stream metadata modification.")
+ return dir
+
+ cmd.append(work_path)
+ LOGGER.info(f"Modifying metadata for file: {file_name}")
+
+ try:
+ async with subprocess_lock:
+ if listener.isCancelled:
+ if work_path.exists():
+ work_path.unlink()
+ return
+ listener.suproc = await create_subprocess_exec(
+ *cmd,
+ stderr=PIPE,
+ stdout=PIPE
+ )
+ (
+ _,
+ stderr
+ ) = await listener.suproc.communicate()
+
+ if listener.suproc.returncode != 0:
+ if work_path.exists():
+ work_path.unlink()
+ if listener.isCancelled:
+ return
+ err = stderr.decode().strip()
+ LOGGER.error(f"Error modifying metadata for file: {file_name} | {err}")
+ return dir
+
+ if work_path.exists():
+ work_path.replace(dir_path)
+ LOGGER.info(f"Metadata modified successfully for file: {file_name}")
+ else:
+ LOGGER.error(f"Temporary file {work_path} not found. Metadata modification failed.")
+
+ except (
+ RuntimeError,
+ OSError
+ ) as e:
+ LOGGER.error(f"Error modifying metadata: {str(e)}")
+ if work_path.exists():
+ work_path.unlink()
+ return dir
+
+ finally:
+ if work_path.exists():
+ work_path.unlink()
+
+ return dir
+
+
+async def add_attachment(listener, dir):
+
+ MIME_TYPES = {
+ "jpg": "image/jpeg",
+ "jpeg": "image/jpeg",
+ "png": "image/png",
+ }
+
+ data = listener.metaAttachment
+ dir_path = Path(dir)
+
+ if dir_path.suffix.lower() not in SUPPORTED_VIDEO_EXTENSIONS:
+ return dir
+
+ file_name = dir_path.name
+ work_path = dir_path.with_suffix(".temp.mkv")
+
+ data_ext = data.split(".")[-1].lower()
+ if not (mime_type := MIME_TYPES.get(data_ext)):
+ LOGGER.error(f"Unsupported attachment type: {data_ext}")
+ return dir
+
+ cmd = [
+ "ffmpeg",
+ "-y",
+ "-i",
+ dir,
+ "-attach",
+ data,
+ "-metadata:s:t",
+ f"mimetype={mime_type}",
+ "-c",
+ "copy",
+ "-map",
+ "0",
+ work_path
+ ]
+
+ try:
+ async with subprocess_lock:
+ if listener.isCancelled:
+ if work_path.exists():
+ work_path.unlink()
+ return
+ listener.suproc = await create_subprocess_exec(
+ *cmd,
+ stderr=PIPE,
+ stdout=PIPE
+ )
+ (
+ _,
+ _
+ ) = await listener.suproc.communicate()
+
+ if listener.suproc.returncode != 0:
+ if work_path.exists():
+ work_path.unlink()
+ if listener.isCancelled:
+ return
+ LOGGER.error(f"Error adding photo attachment to file: {file_name}")
+ return dir
+
+ if work_path.exists():
+ work_path.replace(dir_path)
+ LOGGER.info(f"Photo attachment added successfully to file: {file_name}")
+ else:
+ LOGGER.error(f"Temporary file {work_path} not found. Adding photo attachment failed.")
+
+ except (
+ RuntimeError,
+ OSError
+ ) as e:
+ LOGGER.error(f"Error adding photo attachment: {str(e)}")
+ if work_path.exists():
+ work_path.unlink()
+ return dir
+
+ finally:
+ if work_path.exists():
+ work_path.unlink()
+
+ return dir
diff --git a/bot/helper/ext_utils/status_utils.py b/bot/helper/ext_utils/status_utils.py
index ffa5dcdb1500..85b059a4ac80 100644
--- a/bot/helper/ext_utils/status_utils.py
+++ b/bot/helper/ext_utils/status_utils.py
@@ -44,6 +44,7 @@ class MirrorStatus:
STATUS_SEEDING = "Seed 🌧"
STATUS_SAMVID = "SampleVid 🎬"
STATUS_CONVERTING = "Convert ♻️"
+ STATUS_METADATA = "Metadata 📝"
STATUSES = {
@@ -61,6 +62,7 @@ class MirrorStatus:
"CK": MirrorStatus.STATUS_CHECKING,
"SV": MirrorStatus.STATUS_SAMVID,
"PA": MirrorStatus.STATUS_PAUSED,
+ "MD": MirrorStatus.STATUS_METADATA
}
@@ -264,7 +266,9 @@ async def get_readable_message(
)
if tstatus not in [
MirrorStatus.STATUS_SEEDING,
+ MirrorStatus.STATUS_QUEUEDL,
MirrorStatus.STATUS_QUEUEUP,
+ MirrorStatus.STATUS_METADATA
]:
progress = (
await task.progress()
diff --git a/bot/helper/listeners/task_listener.py b/bot/helper/listeners/task_listener.py
index 2d7d037c6280..64c41758e912 100644
--- a/bot/helper/listeners/task_listener.py
+++ b/bot/helper/listeners/task_listener.py
@@ -301,6 +301,22 @@ async def onDownloadComplete(self):
)
self.size = await get_path_size(up_dir)
+ if self.metaData:
+ await self.proceedMetadata(
+ up_path,
+ gid
+ )
+ if self.isCancelled:
+ return
+
+ if self.metaAttachment:
+ await self.proceedAttachment(
+ up_path,
+ gid
+ )
+ if self.isCancelled:
+ return
+
if self.isLeech and not self.compress:
await self.proceedSplit(
up_dir,
diff --git a/bot/helper/task_utils/status_utils/meta_status.py b/bot/helper/task_utils/status_utils/meta_status.py
new file mode 100644
index 000000000000..bc20cb5e8d71
--- /dev/null
+++ b/bot/helper/task_utils/status_utils/meta_status.py
@@ -0,0 +1,63 @@
+from bot import (
+ LOGGER,
+ subprocess_lock
+)
+from bot.helper.ext_utils.status_utils import (
+ get_readable_file_size,
+ get_readable_time,
+ MirrorStatus
+)
+from subprocess import run as frun
+from time import time
+from bot.helper.ext_utils.files_utils import get_path_size
+
+
+class MetaStatus:
+ def __init__(
+ self,
+ listener,
+ gid
+ ):
+ self.listener = listener
+ self._gid = gid
+ self._size = self.listener.size
+ self._start_time = time()
+ self._proccessed_bytes = 0
+ self.engine = f"FFmpeg v{self._eng_ver()}"
+
+ def _eng_ver(self):
+ _engine = frun(
+ [
+ "ffmpeg",
+ "-version"
+ ],
+ capture_output=True,
+ text=True
+ )
+ return _engine.stdout.split("\n")[0].split(" ")[2].split("-")[0]
+
+ def gid(self):
+ return self._gid
+
+ def name(self):
+ return self.listener.name
+
+ def size(self):
+ return get_readable_file_size(self._size)
+
+ def status(self):
+ return MirrorStatus.STATUS_METADATA
+
+ def task(self):
+ return self
+
+ async def cancel_task(self):
+ LOGGER.info(f"Cancelling metadata editor: {self.listener.name}")
+ self.listener.isCancelled = True
+ async with subprocess_lock:
+ if (
+ self.listener.suproc is not None
+ and self.listener.suproc.returncode is None
+ ):
+ self.listener.suproc.kill()
+ await self.listener.onUploadError("Metadata editing stopped by user!")
diff --git a/bot/helper/task_utils/status_utils/queue_status.py b/bot/helper/task_utils/status_utils/queue_status.py
index cdde4f3a12cf..ce8b0c475d18 100644
--- a/bot/helper/task_utils/status_utils/queue_status.py
+++ b/bot/helper/task_utils/status_utils/queue_status.py
@@ -35,18 +35,6 @@ def status(self):
return MirrorStatus.STATUS_QUEUEDL
return MirrorStatus.STATUS_QUEUEUP
- def processed_bytes(self):
- return 0
-
- def progress(self):
- return "0%"
-
- def speed(self):
- return "0B/s"
-
- def eta(self):
- return "-"
-
def task(self):
return self
diff --git a/bot/helper/task_utils/telegram_uploader.py b/bot/helper/task_utils/telegram_uploader.py
index 30c917fab049..95ff9e0b1649 100644
--- a/bot/helper/task_utils/telegram_uploader.py
+++ b/bot/helper/task_utils/telegram_uploader.py
@@ -372,7 +372,10 @@ async def _send_screenshots(self, dirpath, outputs):
self._sent_DMmsg = None
async def _send_media_group(self, subkey, key, msgs):
- for index, msg in enumerate(msgs):
+ for (
+ index,
+ msg
+ ) in enumerate(msgs):
if self._listener.mixedLeech or not self._user_session: # type: ignore
msgs[index] = await self._listener.client.get_messages(
chat_id=msg[0],
@@ -429,7 +432,11 @@ async def upload(self, o_files, ft_delete):
res = await self._msg_to_reply()
if not res:
return
- for dirpath, _, files in natsorted(
+ for (
+ dirpath,
+ _,
+ files
+ ) in natsorted(
await sync_to_async(
walk,
self._path
@@ -497,8 +504,14 @@ async def upload(self, o_files, ft_delete):
and match.group(0)
not in group_lists
):
- for key, value in list(self._media_dict.items()):
- for subkey, msgs in list(value.items()):
+ for (
+ key,
+ value
+ ) in list(self._media_dict.items()):
+ for (
+ subkey,
+ msgs
+ ) in list(value.items()):
if len(msgs) > 1:
await self._send_media_group(
subkey,
@@ -560,7 +573,10 @@ async def upload(self, o_files, ft_delete):
)
):
await remove(self._up_path)
- for key, value in list(self._media_dict.items()):
+ for (
+ key,
+ value
+ ) in list(self._media_dict.items()):
for subkey, msgs in list(value.items()):
if len(msgs) > 1:
try:
@@ -635,7 +651,7 @@ async def _send_dm(self):
except Exception as err:
if isinstance(err, RPCError):
LOGGER.error(
- f"Error while sending dm {err.NAME}: {err.MESSAGE}")
+ f"Error while sending dm {err.NAME}: {err.MESSAGE}") # type: ignore
else:
LOGGER.error(
f"Error while sending dm {err.__class__.__name__}")
@@ -659,7 +675,11 @@ async def _upload_file(self, cap_mono, file, o_path, force_document=False):
thumb = self._thumb
self._is_corrupted = False
try:
- is_video, is_audio, is_image = await get_document_type(self._up_path)
+ (
+ is_video,
+ is_audio,
+ is_image
+ ) = await get_document_type(self._up_path)
if not is_image and thumb is None:
file_name = ospath.splitext(file)[0]
@@ -706,7 +726,10 @@ async def _upload_file(self, cap_mono, file, o_path, force_document=False):
)
if thumb is not None:
with Image.open(thumb) as img:
- width, height = img.size
+ (
+ width,
+ height
+ ) = img.size
else:
width = 480
height = 320
diff --git a/bot/modules/bot_settings.py b/bot/modules/bot_settings.py
index 447645f24f2e..23e1b8c4b8dc 100644
--- a/bot/modules/bot_settings.py
+++ b/bot/modules/bot_settings.py
@@ -1968,6 +1968,20 @@ async def load_config():
if len(LEECH_CAPTION_FONT) == 0:
LEECH_CAPTION_FONT = ""
+ METADATA_TXT = environ.get(
+ "METADATA_TXT",
+ ""
+ )
+ if len(METADATA_TXT) == 0:
+ METADATA_TXT = ""
+
+ META_ATTACHMENT = environ.get(
+ "META_ATTACHMENT",
+ ""
+ )
+ if len(META_ATTACHMENT) == 0:
+ META_ATTACHMENT = ""
+
SEARCH_PLUGINS = environ.get(
"SEARCH_PLUGINS",
""
@@ -2724,6 +2738,8 @@ async def load_config():
"LEECH_SPLIT_SIZE": LEECH_SPLIT_SIZE,
"MEDIA_GROUP": MEDIA_GROUP,
"MIXED_LEECH": MIXED_LEECH,
+ "METADATA_TXT": METADATA_TXT,
+ "META_ATTACHMENT": META_ATTACHMENT,
"NAME_SUBSTITUTE": NAME_SUBSTITUTE,
"OWNER_ID": OWNER_ID,
"QUEUE_ALL": QUEUE_ALL,
diff --git a/bot/modules/mirror_leech.py b/bot/modules/mirror_leech.py
index 527eec4de0f2..e2702f0d3046 100644
--- a/bot/modules/mirror_leech.py
+++ b/bot/modules/mirror_leech.py
@@ -140,6 +140,8 @@ async def newEvent(self):
"-ca": "", "-convertaudio": "",
"-cv": "", "-convertvideo": "",
"-ns": "", "-namesub": "",
+ "-md": "", "-metadata": "",
+ "-mda": "", "-metaattachment": "",
}
arg_parser(
@@ -167,6 +169,8 @@ async def newEvent(self):
self.convertVideo = args["-cv"] or args["-convertvideo"]
self.nameSub = args["-ns"] or args["-namesub"]
self.mixedLeech = args["-ml"] or args["-mixedleech"]
+ self.metaData = args["-md"] or args["-metadata"]
+ self.metaAttachment = args["-mda"] or args["-metaattachment"]
headers = args["-h"] or args["-headers"]
isBulk = args["-b"] or args["-bulk"]
diff --git a/bot/modules/users_settings.py b/bot/modules/users_settings.py
index 537034394bd9..1a812ff31bd6 100644
--- a/bot/modules/users_settings.py
+++ b/bot/modules/users_settings.py
@@ -190,6 +190,22 @@ async def get_user_settings(from_user):
else:
mixed_leech = "Disabled"
+ if user_dict.get(
+ "metatxt",
+ False
+ ):
+ metatxt = "Added"
+ else:
+ metatxt = "Not Added"
+
+ if user_dict.get(
+ "attachmenturl",
+ False
+ ):
+ attachmenturl = "Added"
+ else:
+ attachmenturl = "Not Added"
+
buttons.ibutton(
"ʟᴇᴇᴄʜ\nꜱᴇᴛᴛɪɴɢꜱ",
f"userset {user_id} leech"
@@ -352,6 +368,8 @@ async def get_user_settings(from_user):
Leech Cap Font :
{lcapfont}
Leech Split Size :
{split_size}
Leech Destination:
{leech_dest}
+Metadata Text :
{metatxt}
+Attachment Url :
{attachmenturl}
Thumbnail :
{thumbmsg}
Equal Splits :
{equal_splits}
@@ -654,6 +672,8 @@ async def edit_user_settings(client, query):
"yt_opt",
"lprefix",
"lsuffix",
+ "metatxt",
+ "attachmenturl",
"lcapfont",
"index_url",
"name_sub",
@@ -877,7 +897,28 @@ async def edit_user_settings(client, query):
)
else:
mixed_leech = "Disabled"
-
+ buttons.ibutton(
+ "ᴍᴇᴛᴀᴅᴀᴛᴀ\nᴛᴇxᴛ",
+ f"userset {user_id} metadata_text"
+ )
+ if user_dict.get(
+ "metatxt",
+ False
+ ):
+ metatxt = user_dict["metatxt"]
+ else:
+ metatxt = "None"
+ buttons.ibutton(
+ "ᴀᴛᴛᴀᴄʜᴍᴇɴᴛ\nᴜʀʟ",
+ f"userset {user_id} attachment_url"
+ )
+ if user_dict.get(
+ "attachmenturl",
+ False
+ ):
+ attachmenturl = user_dict["attachmenturl"]
+ else:
+ attachmenturl = "None"
buttons.ibutton(
"ʙᴀᴄᴋ",
f"userset {user_id} back",
@@ -897,6 +938,8 @@ async def edit_user_settings(client, query):
Leech Suffix :
{escape(lsuffix)}
Leech Cap Font :
{escape(lcapfont)}
Leech Destination:
{leech_dest}
+Metadata Text :
{escape(metatxt)}
+Attachment Url :
{escape(attachmenturl)}
Thumbnail :
{thumbmsg}
Equal Splits :
{equal_splits}
@@ -1428,6 +1471,94 @@ async def edit_user_settings(client, query):
),
update_user_settings(query)
)
+
+ elif data[2] == "metadata_text":
+ await query.answer()
+ buttons = ButtonMaker()
+ if (
+ user_dict.get(
+ "metatxt",
+ False
+ )
+ ):
+ buttons.ibutton(
+ "ʀᴇᴍᴏᴠᴇ\nᴍᴇᴛᴀᴅᴀᴛᴀ ᴛᴇxᴛ",
+ f"userset {user_id} metatxt"
+ )
+ buttons.ibutton(
+ "ʙᴀᴄᴋ",
+ f"userset {user_id} leech"
+ )
+ buttons.ibutton(
+ "ᴄʟᴏꜱᴇ",
+ f"userset {user_id} close"
+ )
+ await editMessage(
+ message,
+ "Send Leech Metadata Text, Whatever You want to add in the Videos.\n\nTimeout: 60 sec",
+ buttons.build_menu(1),
+ )
+ try:
+ event = await event_handler(
+ client,
+ query
+ )
+ except ListenerTimeout:
+ await update_user_settings(query)
+ except ListenerStopped:
+ pass
+ else:
+ await gather(
+ set_option(
+ event,
+ "metatxt"
+ ),
+ update_user_settings(query)
+ )
+
+ elif data[2] == "attachment_url":
+ await query.answer()
+ buttons = ButtonMaker()
+ if (
+ user_dict.get(
+ "attachmenturl",
+ False
+ )
+ ):
+ buttons.ibutton(
+ "ʀᴇᴍᴏᴠᴇ ᴀᴛᴛᴀᴄʜᴍᴇɴᴛ ᴜʀʟ",
+ f"userset {user_id} attachmenturl"
+ )
+ buttons.ibutton(
+ "ʙᴀᴄᴋ",
+ f"userset {user_id} leech"
+ )
+ buttons.ibutton(
+ "ᴄʟᴏꜱᴇ",
+ f"userset {user_id} close"
+ )
+ await editMessage(
+ message,
+ "Send Leech Attachment Url, which you want to get embedded with the video.\n\nTimeout: 60 sec",
+ buttons.build_menu(1),
+ )
+ try:
+ event = await event_handler(
+ client,
+ query
+ )
+ except ListenerTimeout:
+ await update_user_settings(query)
+ except ListenerStopped:
+ pass
+ else:
+ await gather(
+ set_option(
+ event,
+ "attachmenturl"
+ ),
+ update_user_settings(query)
+ )
elif data[2] == "leech_suffix":
await query.answer()
buttons = ButtonMaker()
diff --git a/config_sample.env b/config_sample.env
index 36b4097aaf8e..00c026d827b0 100644
--- a/config_sample.env
+++ b/config_sample.env
@@ -64,6 +64,8 @@ USER_TRANSMISSION = "True" # True or False
MIXED_LEECH = "True" # True or False
USER_LEECH_DESTINATION = "PM" # PM or DM or chat_id
NAME_SUBSTITUTE = ""
+METADATA_TXT = ""
+META_ATTACHMENT = ""
# Super Group Settings
REQUEST_LIMITS = "4" # Enter only numbers in seconds