diff --git a/Dockerfile b/Dockerfile
index a0064670..dc339a2d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -12,7 +12,7 @@ ENV LANGUAGE=en_US:en \
RUN apt-get -qq update && apt-get -qq install -y \
python3 python3-pip locales libmagic-dev \
- p7zip-full p7zip-rar unzip && \
+ p7zip-full p7zip-rar unzip mediainfo ffmpeg && \
locale-gen en_US.UTF-8
COPY requirements.txt .
diff --git a/README.md b/README.md
index c7a3e912..8339e8d5 100644
--- a/README.md
+++ b/README.md
@@ -21,6 +21,9 @@ SearchX is a multipurpose Telegram bot written in Python for Google Drive
- Compress data from Google Drive, AppDrive and GDToT
- Extract data from Google Drive, AppDrive and GDToT
- Count data from Google Drive
+- Generate mediainfo of media files from Google Drive and URL
+- Generate frames of media files from Google Drive and URL
+- Generate collage of media files from Google Drive and URL
- Delete data from Google Drive
- Set data permission in Google Drive
- Size Limit support for Clone, Compression and Extraction tasks
@@ -60,6 +63,9 @@ clone - Clone data to Google Drive
compress - Compress data to Google Drive
extract - Extract data to Google Drive
count - Count data from Google Drive
+minfo - Generate mediainfo of a media file
+ss - Generate frames of a media file
+col - Generate collage of a media file
cancel - Cancel a task
status - Get status of all tasks
share - Set data permission in Google Drive
diff --git a/bot/__main__.py b/bot/__main__.py
index d41fe954..119f6e2e 100644
--- a/bot/__main__.py
+++ b/bot/__main__.py
@@ -7,7 +7,7 @@
from telegram.ext import CommandHandler
from bot import bot, LOGGER, botStartTime, TELEGRAPH, Interval, dispatcher, updater
-from bot.modules import archive, auth, bookmark, cancel, clone, count, delete, eval, list, permission, shell, status
+from bot.modules import archive, auth, bookmark, cancel, clone, collage, count, delete, eval, frames, list, mediainfo, permission, shell, status
from bot.helper.ext_utils.bot_utils import get_readable_file_size, get_readable_time
from bot.helper.ext_utils.fs_utils import start_cleanup, clean_all, exit_clean_up
from bot.helper.telegram_helper.bot_commands import BotCommands
@@ -78,6 +78,12 @@ def restart(update, context):
• /{BotCommands.CountCommand} <drive_url>: Count data from Google Drive
+• /{BotCommands.MediainfoCommand} <url>: Generate mediainfo of a media file from Google Drive and URL
+
+• /{BotCommands.FramesCommand} <url> <count>: Generate frames of a media file from Google Drive and URL (Count optional)
+
+• /{BotCommands.CollageCommand} <url> <grid>: Generate collage of a media file from Google Drive and URL (Grid optional)
+
• /{BotCommands.CancelCommand} <gid>: Cancel a task
• /{BotCommands.StatusCommand}: Get status of all tasks
diff --git a/bot/helper/drive_utils/gdriveTools.py b/bot/helper/drive_utils/gdriveTools.py
index 1ac83a78..dfb02ba6 100644
--- a/bot/helper/drive_utils/gdriveTools.py
+++ b/bot/helper/drive_utils/gdriveTools.py
@@ -117,6 +117,14 @@ def __alt_authorize(self):
LOGGER.error("The token.json file is missing")
return None
+ def __get_access_token(self):
+ creds = None
+ if os.path.exists('token.json'):
+ creds = Credentials.from_authorized_user_file('token.json', self.__OAUTH_SCOPE)
+ if creds and creds.expired and creds.refresh_token:
+ creds.refresh(Request())
+ return creds.token
+
def __switchServiceAccount(self):
if self.__service_account_index == SERVICE_ACCOUNTS_NUMBER - 1:
self.__service_account_index = 0
@@ -169,6 +177,36 @@ def __getFilesByFolderId(self, folder_id):
break
return files
+ def fileinfo(self, link):
+ try:
+ file_id = self.__getIdFromUrl(link)
+ except (KeyError, IndexError):
+ msg = "Drive ID not found"
+ LOGGER.error(msg)
+ return msg, "", "", "", "", ""
+ try:
+ access_token = self.__get_access_token()
+ meta = self.__getFileMetadata(file_id)
+ name = meta.get("name")
+ size = get_readable_file_size(int(meta.get("size", 0)))
+ mime_type = meta.get("mimeType")
+ except Exception as err:
+ if isinstance(err, RetryError):
+ LOGGER.info(f"Total attempts: {err.last_attempt.attempt_number}")
+ err = err.last_attempt.exception()
+ err = str(err).replace('>', '').replace('<', '')
+ if "File not found" in err:
+ token_service = self.__alt_authorize()
+ if token_service is not None:
+ self.__service = token_service
+ return self.fileinfo(link)
+ msg = "File not found"
+ else:
+ msg = err
+ LOGGER.error(msg)
+ return msg, "", "", "", "", ""
+ return "", file_id, access_token, name, size, mime_type
+
def __gDrive_file(self, filee):
size = int(filee.get('size', 0))
self.__total_bytes += size
diff --git a/bot/helper/ext_utils/bot_utils.py b/bot/helper/ext_utils/bot_utils.py
index e0f12b7a..d9846c01 100644
--- a/bot/helper/ext_utils/bot_utils.py
+++ b/bot/helper/ext_utils/bot_utils.py
@@ -1,9 +1,12 @@
+import os
import re
+import requests
import threading
import time
from html import escape
from psutil import virtual_memory, cpu_percent, disk_usage
+from requests_toolbelt import MultipartEncoder
from bot.helper.telegram_helper.bot_commands import BotCommands
from bot import botStartTime, DOWNLOAD_DIR, download_dict, download_dict_lock
@@ -115,6 +118,37 @@ def get_readable_time(seconds: int) -> str:
result += f'{seconds}s'
return result
+def slowpics_collection(path):
+ img_list = os.listdir(path)
+ data = {
+ "collectionName": "SearchX",
+ "hentai": "false",
+ "optimizeImages": "false",
+ "public": "false"
+ }
+ for i in range(0, len(img_list)):
+ data[f"images[{i}].name"] = img_list[i]
+ data[f"images[{i}].file"] = (img_list[i], open(f"{path}/{img_list[i]}", 'rb'), 'image/png')
+ with requests.Session() as client:
+ client.get('https://slow.pics/api/collection')
+ files = MultipartEncoder(data)
+ length = str(files.len)
+ headers = {
+ "Accept": "*/*",
+ "Accept-Encoding": "gzip, deflate, br",
+ "Accept-Language": "en-US,en;q=0.5",
+ "Content-Length": length,
+ "Content-Type": files.content_type,
+ "Origin": "https://slow.pics/",
+ "Referer": "https://slow.pics/collection",
+ "Sec-Fetch-Mode": "cors",
+ "Sec-Fetch-Site": "same-origin",
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36",
+ "X-XSRF-TOKEN": client.cookies.get_dict()["XSRF-TOKEN"]
+ }
+ response = client.post("https://slow.pics/api/collection", data=files, headers=headers)
+ return f"https://slow.pics/c/{response.text}"
+
def is_url(url: str):
url = re.findall(URL_REGEX, url)
return bool(url)
diff --git a/bot/helper/telegram_helper/bot_commands.py b/bot/helper/telegram_helper/bot_commands.py
index bcd9c646..6da6343f 100644
--- a/bot/helper/telegram_helper/bot_commands.py
+++ b/bot/helper/telegram_helper/bot_commands.py
@@ -7,6 +7,9 @@ def __init__(self):
self.CompressCommand = 'compress'
self.ExtractCommand = 'extract'
self.CountCommand = 'count'
+ self.MediainfoCommand = 'minfo'
+ self.FramesCommand = 'ss'
+ self.CollageCommand = 'col'
self.CancelCommand = 'cancel'
self.StatusCommand = 'status'
self.PermissionCommand = 'share'
diff --git a/bot/modules/collage.py b/bot/modules/collage.py
new file mode 100644
index 00000000..8dce875a
--- /dev/null
+++ b/bot/modules/collage.py
@@ -0,0 +1,189 @@
+import datetime
+import mimetypes
+import os
+import random
+import requests
+import string
+import subprocess
+
+from PIL import Image, ImageFont, ImageDraw, ImageOps
+from telegram.ext import CommandHandler
+from urllib.parse import unquote_plus
+
+from bot import LOGGER, DOWNLOAD_DIR, dispatcher
+from bot.helper.drive_utils.gdriveTools import GoogleDriveHelper
+from bot.helper.ext_utils.bot_utils import new_thread, get_readable_file_size, slowpics_collection, is_url, is_gdrive_link
+from bot.helper.ext_utils.exceptions import DDLExceptionHandler
+from bot.helper.ext_utils.fs_utils import clean_download
+from bot.helper.telegram_helper.message_utils import sendMessage, deleteMessage
+from bot.helper.telegram_helper.bot_commands import BotCommands
+from bot.helper.telegram_helper.button_builder import ButtonMaker
+from bot.helper.telegram_helper.filters import CustomFilters
+
+@new_thread
+def collageNode(update, context):
+ args = update.message.text.split()
+ reply_to = update.message.reply_to_message
+ link = ''
+ grid = ''
+ row = 4
+ col = 4
+ if len(args) > 1:
+ link = args[1].strip()
+ try:
+ grid = args[2].split("x", maxsplit=1)
+ row = int(grid[0])
+ col = int(grid[1])
+ except (IndexError, ValueError):
+ pass
+ if reply_to:
+ link = reply_to.text.split(maxsplit=1)[0].strip()
+ try:
+ grid = args[1].split("x", maxsplit=1)
+ row = int(grid[0])
+ col = int(grid[1])
+ except (IndexError, ValueError):
+ pass
+ if row > 5 or col > 5:
+ row = 5
+ col = 5
+ elif row != col:
+ row = 4
+ col = 4
+ if is_url(link):
+ msg = sendMessage(f"Getting {row}x{col} collage: {link}
", context.bot, update.message)
+ LOGGER.info(f"Getting {row}x{col} collage: {link}")
+ if is_gdrive_link(link):
+ try:
+ gd = GoogleDriveHelper()
+ res, file_id, access_token, name, size, mime_type = gd.fileinfo(link)
+ if res != "":
+ deleteMessage(context.bot, msg)
+ return sendMessage(res, context.bot, update.message)
+ if mime_type == "application/vnd.google-apps.folder":
+ raise DDLExceptionHandler("Folder is not supported")
+ file_dl = f"https://www.googleapis.com/drive/v3/files/{file_id}\?supportsAllDrives\=true\&alt\=media"
+ header = f"Authorization: Bearer {access_token}"
+ out = subprocess.run(f"ffprobe -headers '{header}' -i {file_dl} -show_entries format=duration -v error -of csv=p=0", capture_output=True, shell=True)
+ stderr = out.stderr.decode('utf-8')
+ if "403 Forbidden" in stderr:
+ raise DDLExceptionHandler("Download quota exceeded")
+ duration = out.stdout.decode('utf-8')
+ if duration == '':
+ raise ValueError("Unsupported media file")
+ durationhms = str(datetime.timedelta(seconds=int(float(duration))))
+ uid = ''.join(random.SystemRandom().choices(string.ascii_letters + string.digits, k=12))
+ path = f"{DOWNLOAD_DIR}{uid}"
+ os.makedirs(path)
+ for seconds in random.sample(range(int(float(duration))), int(row*col)):
+ img = ''.join(random.SystemRandom().choices(string.ascii_letters + string.digits, k=3))
+ genss = subprocess.run(f"ffmpeg -headers '{header}' -hide_banner -ss {seconds} -i {file_dl} -frames:v 1 -q:v 2 -y {path}/{img}.png", capture_output=True, shell=True)
+ if "403 Forbidden" in genss.stderr.decode('utf-8'):
+ raise DDLExceptionHandler("Download quota exceeded fucker")
+ img_list = os.listdir(path)
+ images = [Image.open(fp) for fp in [os.path.join(path, file) for file in img_list]]
+ widths, heights = zip(*(i.size for i in images))
+ max_width = max(widths)
+ max_height = max(heights)
+ canvas_width = max_width*row
+ canvas_height = max_height*col
+ canvas = Image.new(mode="RGB", size=(canvas_width, canvas_height), color=(0, 0, 0))
+ tile_count=0
+ for j in range(0, canvas_height - 1, max_height):
+ for i in range(0, canvas_width - 1, max_width):
+ im = Image.open(f'{path}/{img_list[tile_count]}')
+ canvas.paste(im, box=(i, j))
+ tile_count+=1
+ canvas_exp = ImageOps.expand(canvas, border=(0,int(canvas_height/6.5),0,0), fill=(0, 0, 0))
+ draw = ImageDraw.Draw(canvas_exp)
+ text = f"{name}\nSize: {size}\nDuration: {durationhms}\nDimension: {max_width}x{max_height}"
+ font = ImageFont.truetype(font="/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", size=int(canvas_height/30))
+ draw.text((30,10), text=text, fill=(255, 255, 255), font=font)
+ collage_path = f"{path}/collage"
+ os.makedirs(collage_path)
+ img = ''.join(random.SystemRandom().choices(string.ascii_letters + string.digits, k=4))
+ canvas_res = canvas_exp.resize(size=(max_width, max_height))
+ canvas_res.save(f"{collage_path}/{img}.png")
+ img_link = slowpics_collection(collage_path)
+ LOGGER.info(f"img limk {img_link}")
+ result = ""
+ result += f"Name: {name}
"
+ result += f"\nSize: {size}
"
+ result += f"\nType: {mime_type}
"
+ button = ButtonMaker()
+ button.build_button("VIEW COLLAGE 🗂️", f"{img_link}")
+ clean_download(path)
+ deleteMessage(context.bot, msg)
+ sendMessage(result, context.bot, update.message, button.build_menu(1))
+ except Exception as err:
+ deleteMessage(context.bot, msg)
+ LOGGER.error(str(err))
+ return sendMessage(str(err), context.bot, update.message)
+ else:
+ try:
+ res = requests.head(link, stream=True)
+ name = unquote_plus(link).rsplit('/', 1)[-1]
+ size = get_readable_file_size(int(res.headers["Content-Length"].strip()))
+ mime_type = res.headers.get("Content-Type", mimetypes.guess_type(name)).rsplit(";", 1)[0]
+ out = subprocess.run(["ffprobe", "-i", f"{link}", "-show_entries", "format=duration", "-v", "quiet", "-of", "csv=p=0"], capture_output=True)
+ duration = out.stdout.decode('utf-8')
+ if duration == '':
+ raise ValueError("Unsupported media file")
+ durationhms = str(datetime.timedelta(seconds=int(float(duration))))
+ uid = ''.join(random.SystemRandom().choices(string.ascii_letters + string.digits, k=12))
+ path = f"{DOWNLOAD_DIR}{uid}"
+ os.makedirs(path)
+ sscount=1
+ for seconds in random.sample(range(int(float(duration))), int(row*col)):
+ img = ''.join(random.SystemRandom().choices(string.ascii_letters + string.digits, k=4))
+ genss = subprocess.run(["ffmpeg", "-hide_banner", "-ss", f"{seconds}", "-i", f"{link}", "-frames:v", "1", "-q:v", "2", "-y", f"{path}/{img}.png"], capture_output=True)
+ sscount+=1
+ img_list = os.listdir(path)
+ images = [Image.open(fp) for fp in [os.path.join(path, file) for file in img_list]]
+ widths, heights = zip(*(i.size for i in images))
+ max_width = max(widths)
+ max_height = max(heights)
+ canvas_width = max_width*row
+ canvas_height = max_height*col
+ canvas = Image.new(mode="RGB", size=(canvas_width, canvas_height), color=(0, 0, 0))
+ tile_count=0
+ for j in range(0, canvas_height - 1, max_height):
+ for i in range(0, canvas_width - 1, max_width):
+ im = Image.open(f'{path}/{img_list[tile_count]}')
+ canvas.paste(im, box=(i, j))
+ tile_count+=1
+ canvas_exp = ImageOps.expand(canvas, border=(0,int(canvas_height/6.5),0,0), fill=(0, 0, 0))
+ draw = ImageDraw.Draw(canvas_exp)
+ text = f"{name}\nSize: {size}\nDuration: {durationhms}\nDimension: {max_width}x{max_height}"
+ font = ImageFont.truetype(font="/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", size=int(canvas_height/30))
+ draw.text((30,10), text=text, fill=(255, 255, 255), font=font)
+ collage_path = f"{path}/collage"
+ os.makedirs(collage_path)
+ img = ''.join(random.SystemRandom().choices(string.ascii_letters + string.digits, k=4))
+ canvas_res = canvas_exp.resize(size=(max_width, max_height))
+ canvas_res.save(f"{collage_path}/{img}.png")
+ img_link = slowpics_collection(collage_path)
+ result = ""
+ result += f"Name: {name}
"
+ result += f"\nSize: {size}
"
+ result += f"\nType: {mime_type}
"
+ button = ButtonMaker()
+ button.build_button("VIEW COLLAGE 🗂️", f"{img_link}")
+ clean_download(path)
+ deleteMessage(context.bot, msg)
+ sendMessage(result, context.bot, update.message, button.build_menu(1))
+ except KeyError:
+ deleteMessage(context.bot, msg)
+ err = "Invalid link"
+ LOGGER.error(str(err))
+ return sendMessage(str(err), context.bot, update.message)
+ except Exception as err:
+ deleteMessage(context.bot, msg)
+ LOGGER.error(str(err))
+ return sendMessage(str(err), context.bot, update.message)
+ else:
+ sendMessage("Send a link along with command", context.bot, update.message)
+
+collage_handler = CommandHandler(BotCommands.CollageCommand, collageNode,
+ filters=CustomFilters.authorized_user | CustomFilters.authorized_chat)
+dispatcher.add_handler(collage_handler)
diff --git a/bot/modules/frames.py b/bot/modules/frames.py
new file mode 100644
index 00000000..82e26208
--- /dev/null
+++ b/bot/modules/frames.py
@@ -0,0 +1,126 @@
+import mimetypes
+import os
+import random
+import requests
+import string
+import subprocess
+
+from telegram.ext import CommandHandler
+from urllib.parse import unquote_plus
+
+from bot import LOGGER, DOWNLOAD_DIR, dispatcher
+from bot.helper.drive_utils.gdriveTools import GoogleDriveHelper
+from bot.helper.ext_utils.bot_utils import new_thread, get_readable_file_size, slowpics_collection, is_url, is_gdrive_link
+from bot.helper.ext_utils.exceptions import DDLExceptionHandler
+from bot.helper.ext_utils.fs_utils import clean_download
+from bot.helper.telegram_helper.message_utils import sendMessage, deleteMessage
+from bot.helper.telegram_helper.bot_commands import BotCommands
+from bot.helper.telegram_helper.button_builder import ButtonMaker
+from bot.helper.telegram_helper.filters import CustomFilters
+
+@new_thread
+def framesNode(update, context):
+ args = update.message.text.split()
+ reply_to = update.message.reply_to_message
+ link = ''
+ frames = 5
+ if len(args) > 1:
+ link = args[1].strip()
+ try:
+ frames = int(args[2])
+ except (IndexError, ValueError):
+ pass
+ if reply_to:
+ link = reply_to.text.split(maxsplit=1)[0].strip()
+ try:
+ frames = int(args[1])
+ except (IndexError, ValueError):
+ pass
+ if frames > 10:
+ frames = 10
+ if is_url(link):
+ msg = sendMessage(f"Getting {frames} frames: {link}
", context.bot, update.message)
+ LOGGER.info(f"Getting {frames} frames: {link}")
+ if is_gdrive_link(link):
+ try:
+ gd = GoogleDriveHelper()
+ res, file_id, access_token, name, size, mime_type = gd.fileinfo(link)
+ if res != "":
+ deleteMessage(context.bot, msg)
+ return sendMessage(res, context.bot, update.message)
+ if mime_type == "application/vnd.google-apps.folder":
+ raise DDLExceptionHandler("Folder is not supported")
+ file_dl = f"https://www.googleapis.com/drive/v3/files/{file_id}\?supportsAllDrives\=true\&alt\=media"
+ header = f"Authorization: Bearer {access_token}"
+ out = subprocess.run(f"ffprobe -headers '{header}' -i {file_dl} -show_entries format=duration -v error -of csv=p=0", capture_output=True, shell=True)
+ stderr = out.stderr.decode('utf-8')
+ if "403 Forbidden" in stderr:
+ raise DDLExceptionHandler("Download quota exceeded")
+ duration = out.stdout.decode('utf-8')
+ if duration == '':
+ raise ValueError("Unsupported media file")
+ uid = ''.join(random.SystemRandom().choices(string.ascii_letters + string.digits, k=12))
+ path = f"{DOWNLOAD_DIR}{uid}"
+ os.makedirs(path)
+ for seconds in random.sample(range(int(float(duration))), int(f"{frames}")):
+ img = ''.join(random.SystemRandom().choices(string.ascii_letters + string.digits, k=3))
+ genss = subprocess.run(f"ffmpeg -headers '{header}' -hide_banner -ss {seconds} -i {file_dl} -frames:v 1 -q:v 2 -y {path}/{img}.png", capture_output=True, shell=True)
+ if "403 Forbidden" in genss.stderr.decode('utf-8'):
+ raise DDLExceptionHandler("Download quota exceeded")
+ img_link = slowpics_collection(path)
+ result = ""
+ result += f"Name: {name}
"
+ result += f"\nSize: {size}
"
+ result += f"\nType: {mime_type}
"
+ button = ButtonMaker()
+ button.build_button("VIEW FRAMES 🗂️", f"{img_link}")
+ clean_download(path)
+ deleteMessage(context.bot, msg)
+ sendMessage(result, context.bot, update.message, button.build_menu(1))
+ except Exception as err:
+ deleteMessage(context.bot, msg)
+ LOGGER.error(str(err))
+ return sendMessage(str(err), context.bot, update.message)
+ else:
+ try:
+ res = requests.head(link, stream=True)
+ name = unquote_plus(link).rsplit('/', 1)[-1]
+ size = get_readable_file_size(int(res.headers["Content-Length"].strip()))
+ mime_type = res.headers.get("Content-Type", mimetypes.guess_type(name)).rsplit(";", 1)[0]
+ out = subprocess.run(["ffprobe", "-i", f"{link}", "-show_entries", "format=duration", "-v", "quiet", "-of", "csv=p=0"], capture_output=True)
+ duration = out.stdout.decode('utf-8')
+ if duration == '':
+ raise ValueError("Unsupported media file")
+ uid = ''.join(random.SystemRandom().choices(string.ascii_letters + string.digits, k=12))
+ path = f"{DOWNLOAD_DIR}{uid}"
+ os.makedirs(path)
+ sscount=1
+ for seconds in random.sample(range(int(float(duration))), int(f"{frames}")):
+ img = ''.join(random.SystemRandom().choices(string.ascii_letters + string.digits, k=4))
+ genss = subprocess.run(["ffmpeg", "-hide_banner", "-ss", f"{seconds}", "-i", f"{link}", "-frames:v", "1", "-q:v", "2", "-y", f"{path}/{img}.png"], capture_output=True)
+ sscount+=1
+ img_link = slowpics_collection(path)
+ result = ""
+ result += f"Name: {name}
"
+ result += f"\nSize: {size}
"
+ result += f"\nType: {mime_type}
"
+ button = ButtonMaker()
+ button.build_button("VIEW FRAMES 🗂️", f"{img_link}")
+ clean_download(path)
+ deleteMessage(context.bot, msg)
+ sendMessage(result, context.bot, update.message, button.build_menu(1))
+ except KeyError:
+ deleteMessage(context.bot, msg)
+ err = "Invalid link"
+ LOGGER.error(str(err))
+ return sendMessage(str(err), context.bot, update.message)
+ except Exception as err:
+ deleteMessage(context.bot, msg)
+ LOGGER.error(str(err))
+ return sendMessage(str(err), context.bot, update.message)
+ else:
+ sendMessage("Send a link along with command", context.bot, update.message)
+
+frames_handler = CommandHandler(BotCommands.FramesCommand, framesNode,
+ filters=CustomFilters.authorized_user | CustomFilters.authorized_chat)
+dispatcher.add_handler(frames_handler)
diff --git a/bot/modules/mediainfo.py b/bot/modules/mediainfo.py
new file mode 100644
index 00000000..b035d3cd
--- /dev/null
+++ b/bot/modules/mediainfo.py
@@ -0,0 +1,98 @@
+import mimetypes
+import requests
+import subprocess
+
+from telegram.ext import CommandHandler
+from urllib.parse import unquote_plus
+
+from bot import LOGGER, TELEGRAPH, dispatcher
+from bot.helper.drive_utils.gdriveTools import GoogleDriveHelper
+from bot.helper.ext_utils.bot_utils import new_thread, get_readable_file_size, is_url, is_gdrive_link
+from bot.helper.ext_utils.exceptions import DDLExceptionHandler
+from bot.helper.telegram_helper.message_utils import sendMessage, deleteMessage
+from bot.helper.telegram_helper.bot_commands import BotCommands
+from bot.helper.telegram_helper.button_builder import ButtonMaker
+from bot.helper.telegram_helper.filters import CustomFilters
+
+@new_thread
+def mediainfoNode(update, context):
+ reply_to = update.message.reply_to_message
+ link = ''
+ if len(context.args) == 1:
+ link = context.args[0]
+ if reply_to:
+ link = reply_to.text.split(maxsplit=1)[0].strip()
+ if is_url(link):
+ msg = sendMessage(f"Getting mediainfo: {link}
", context.bot, update.message)
+ LOGGER.info(f"Getting mediainfo: {link}")
+ if is_gdrive_link(link):
+ try:
+ gd = GoogleDriveHelper()
+ res, file_id, access_token, name, size, mime_type = gd.fileinfo(link)
+ if res != "":
+ deleteMessage(context.bot, msg)
+ return sendMessage(res, context.bot, update.message)
+ if mime_type == "application/vnd.google-apps.folder":
+ raise DDLExceptionHandler("Folder is not supported")
+ file_dl = f"https://www.googleapis.com/drive/v3/files/{file_id}\?supportsAllDrives\=true\&alt\=media"
+ header = f"--file_curl=HttpHeader,Authorization: Bearer {access_token}"
+ out = subprocess.run(f"mediainfo '{header}' {file_dl}", capture_output=True, shell=True)
+ stderr = out.stderr.decode('utf-8')
+ if "downloadQuotaExceeded" in stderr or "cannotDownloadFile" in stderr:
+ raise DDLExceptionHandler("Download quota exceeded")
+ stdout = out.stdout.decode('utf-8')
+ metadata = stdout.replace(file_dl.replace("\\", ""), name)
+ page = TELEGRAPH[0].create_page(
+ title='SearchX Mediainfo',
+ author_name='Levi',
+ author_url='https://t.me/l3v11',
+ html_content=f'
{metadata}')['path'] + result = "" + result += f"Name:
{name}
"
+ result += f"\nSize: {size}
"
+ result += f"\nType: {mime_type}
"
+ button = ButtonMaker()
+ button.build_button("VIEW MEDIAINFO 🗂️", f"https://graph.org/{page}")
+ deleteMessage(context.bot, msg)
+ sendMessage(result, context.bot, update.message, button.build_menu(1))
+ except Exception as err:
+ deleteMessage(context.bot, msg)
+ LOGGER.error(str(err))
+ return sendMessage(str(err), context.bot, update.message)
+ else:
+ try:
+ res = requests.head(link, stream=True)
+ name = unquote_plus(link).rsplit('/', 1)[-1]
+ size = get_readable_file_size(int(res.headers["Content-Length"].strip()))
+ mime_type = res.headers.get("Content-Type", mimetypes.guess_type(name)).rsplit(";", 1)[0]
+ out = subprocess.run(["mediainfo", f"{link}"], capture_output=True)
+ stdout = out.stdout.decode('utf-8')
+ metadata = stdout.replace(link, name)
+ page = TELEGRAPH[0].create_page(
+ title='SearchX Mediainfo',
+ author_name='Levi',
+ author_url='https://t.me/l3v11',
+ html_content=f'{metadata}')['path'] + result = "" + result += f"Name:
{name}
"
+ result += f"\nSize: {size}
"
+ result += f"\nType: {mime_type}
"
+ button = ButtonMaker()
+ button.build_button("VIEW MEDIAINFO 🗂️", f"https://graph.org/{page}")
+ deleteMessage(context.bot, msg)
+ sendMessage(result, context.bot, update.message, button.build_menu(1))
+ except KeyError:
+ deleteMessage(context.bot, msg)
+ err = "Invalid link"
+ LOGGER.error(str(err))
+ return sendMessage(str(err), context.bot, update.message)
+ except Exception as err:
+ deleteMessage(context.bot, msg)
+ LOGGER.error(str(err))
+ return sendMessage(str(err), context.bot, update.message)
+ else:
+ sendMessage("Send a link along with command", context.bot, update.message)
+
+mediainfo_handler = CommandHandler(BotCommands.MediainfoCommand, mediainfoNode,
+ filters=CustomFilters.authorized_user | CustomFilters.authorized_chat)
+dispatcher.add_handler(mediainfo_handler)
diff --git a/requirements.txt b/requirements.txt
index 1d5ac517..18bab810 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,11 +1,13 @@
dnspython
google-api-python-client
google-auth-oauthlib
+pillow
psutil
pymongo
python-dotenv
python-magic
python-telegram-bot==13.15
requests
+requests-toolbelt
telegraph
tenacity