mirror of
https://github.com/anonymousx97/social-dl.git
synced 2025-02-20 11:13:19 +08:00
v2.2.0
Fixes: • Sender Now shows Correct name while downloading replied media. • Clean up code for YoutubeDL. • Format code according to PEP. Added: • .cancel to cancel a command/media download execution. • switch to @cached_property decorator and clean up message.py • Parse replied message using custom message class. • Rename tools to dev_tools and move loader to it. • self-destructing responses.
This commit is contained in:
parent
2b41731e84
commit
216e0dcfe1
@ -1,14 +1,15 @@
|
||||
from dotenv import load_dotenv
|
||||
import os
|
||||
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv("config.env")
|
||||
|
||||
from .config import Config
|
||||
from .core.client import BOT
|
||||
|
||||
import os
|
||||
|
||||
if not os.environ.get("TERMUX_APK_RELEASE"):
|
||||
import uvloop
|
||||
|
||||
uvloop.install()
|
||||
|
||||
bot = BOT()
|
||||
|
@ -1,6 +1,8 @@
|
||||
if __name__ == "__main__":
|
||||
import tracemalloc
|
||||
|
||||
tracemalloc.start()
|
||||
|
||||
from app import bot
|
||||
|
||||
bot.run(bot.boot())
|
||||
|
@ -11,14 +11,15 @@ class Gallery_DL(ScraperConfig):
|
||||
def __init__(self, url):
|
||||
super().__init__()
|
||||
self.url = url
|
||||
self.set_sauce(url)
|
||||
|
||||
async def download_or_extract(self):
|
||||
self.path = "downloads/" + str(time.time())
|
||||
os.makedirs(self.path)
|
||||
try:
|
||||
async with asyncio.timeout(30):
|
||||
await shell.run_shell_cmd(f"gallery-dl -q --range '0-4' -D {self.path} '{self.url}'")
|
||||
await shell.run_shell_cmd(
|
||||
f"gallery-dl -q --range '0-4' -D {self.path} '{self.url}'"
|
||||
)
|
||||
except TimeoutError:
|
||||
pass
|
||||
files = glob.glob(f"{self.path}/*")
|
||||
|
@ -9,7 +9,6 @@ from app.core.scraper_config import ScraperConfig
|
||||
class Reddit(ScraperConfig):
|
||||
def __init__(self, url):
|
||||
super().__init__()
|
||||
self.set_sauce(url)
|
||||
parsed_url = urlparse(url)
|
||||
self.url = f"https://www.reddit.com{parsed_url.path}.json?limit=1"
|
||||
|
||||
@ -17,7 +16,9 @@ class Reddit(ScraperConfig):
|
||||
headers = {
|
||||
"user-agent": "Mozilla/5.0 (Macintosh; PPC Mac OS X 10_8_7 rv:5.0; en-US) AppleWebKit/533.31.5 (KHTML, like Gecko) Version/4.0 Safari/533.31.5"
|
||||
}
|
||||
response = await aiohttp_tools.get_json(url=self.url, headers=headers, json_=True)
|
||||
response = await aiohttp_tools.get_json(
|
||||
url=self.url, headers=headers, json_=True
|
||||
)
|
||||
if not response:
|
||||
return
|
||||
|
||||
@ -26,7 +27,9 @@ class Reddit(ScraperConfig):
|
||||
except BaseException:
|
||||
return
|
||||
|
||||
self.caption = f"""__{json_["subreddit_name_prefixed"]}:__\n**{json_["title"]}**"""
|
||||
self.caption = (
|
||||
f"""__{json_["subreddit_name_prefixed"]}:__\n**{json_["title"]}**"""
|
||||
)
|
||||
|
||||
is_vid, is_gallery = json_.get("is_video"), json_.get("is_gallery")
|
||||
|
||||
@ -35,16 +38,26 @@ class Reddit(ScraperConfig):
|
||||
os.makedirs(self.path)
|
||||
self.link = f"{self.path}/v.mp4"
|
||||
vid_url = json_["secure_media"]["reddit_video"]["hls_url"]
|
||||
await shell.run_shell_cmd(f'ffmpeg -hide_banner -loglevel error -i "{vid_url.strip()}" -c copy {self.link}')
|
||||
await shell.run_shell_cmd(
|
||||
f'ffmpeg -hide_banner -loglevel error -i "{vid_url.strip()}" -c copy {self.link}'
|
||||
)
|
||||
self.thumb = await shell.take_ss(video=self.link, path=self.path)
|
||||
self.video = self.success = True
|
||||
|
||||
elif is_gallery:
|
||||
self.link = [val["s"].get("u", val["s"].get("gif")).replace("preview", "i") for val in json_["media_metadata"].values()]
|
||||
self.link = [
|
||||
val["s"].get("u", val["s"].get("gif")).replace("preview", "i")
|
||||
for val in json_["media_metadata"].values()
|
||||
]
|
||||
self.group = self.success = True
|
||||
|
||||
else:
|
||||
self.link = json_.get("preview", {}).get("reddit_video_preview", {}).get("fallback_url", json_.get("url_overridden_by_dest", "")).strip()
|
||||
self.link = (
|
||||
json_.get("preview", {})
|
||||
.get("reddit_video_preview", {})
|
||||
.get("fallback_url", json_.get("url_overridden_by_dest", ""))
|
||||
.strip()
|
||||
)
|
||||
if not self.link:
|
||||
return
|
||||
if self.link.endswith(".gif"):
|
||||
|
@ -11,12 +11,15 @@ class Threads(ScraperConfig):
|
||||
def __init__(self, url):
|
||||
super().__init__()
|
||||
self.url = url
|
||||
self.set_sauce(url)
|
||||
|
||||
async def download_or_extract(self):
|
||||
shortcode = os.path.basename(urlparse(self.url).path.rstrip("/"))
|
||||
|
||||
response = await (await aiohttp_tools.SESSION.get(f"https://www.threads.net/t/{shortcode}/embed/")).text()
|
||||
response = await (
|
||||
await aiohttp_tools.SESSION.get(
|
||||
f"https://www.threads.net/t/{shortcode}/embed/"
|
||||
)
|
||||
).text()
|
||||
|
||||
soup = BeautifulSoup(response, "html.parser")
|
||||
|
||||
|
@ -8,7 +8,6 @@ class Tiktok(ScraperConfig):
|
||||
def __init__(self, url):
|
||||
super().__init__()
|
||||
self.url = url
|
||||
self.set_sauce(url)
|
||||
|
||||
async def download_or_extract(self):
|
||||
media = await tiktok_scraper.hybrid_parsing(self.url)
|
||||
|
@ -24,7 +24,6 @@ class FakeLogger(object):
|
||||
class YT_DL(ScraperConfig):
|
||||
def __init__(self, url):
|
||||
super().__init__()
|
||||
self.set_sauce(url)
|
||||
self.url = url
|
||||
self.path = "downloads/" + str(time.time())
|
||||
self.video_path = self.path + "/v.mp4"
|
||||
@ -35,30 +34,42 @@ class YT_DL(ScraperConfig):
|
||||
"quiet": True,
|
||||
"logger": FakeLogger(),
|
||||
"noplaylist": True,
|
||||
"format": "best[ext=mp4]",
|
||||
}
|
||||
self.set_format()
|
||||
|
||||
async def download_or_extract(self):
|
||||
if "youtu" in self.url:
|
||||
if "/playlist" in self.url or "/live" in self.url or os.path.basename(self.url).startswith("@"):
|
||||
return
|
||||
self._opts["format"] = "bv[ext=mp4][res=480]+ba[ext=m4a]/b[ext=mp4]"
|
||||
if "/shorts" in self.url:
|
||||
self._opts["format"] = "bv[ext=mp4][res=720]+ba[ext=m4a]/b[ext=mp4]"
|
||||
|
||||
yt_obj = yt_dlp.YoutubeDL(self._opts)
|
||||
|
||||
info = yt_obj.extract_info(self.url, download=False)
|
||||
|
||||
if not info or info.get("duration", 0) >= 300:
|
||||
if self.check_url():
|
||||
return
|
||||
with yt_dlp.YoutubeDL(self._opts) as yt_obj:
|
||||
info = await asyncio.to_thread(
|
||||
yt_obj.extract_info, self.url, download=False
|
||||
)
|
||||
|
||||
await asyncio.to_thread(yt_obj.download, self.url)
|
||||
if not info or info.get("duration", 0) >= 300:
|
||||
return
|
||||
|
||||
if "youtu" in self.url:
|
||||
self.caption = f"""__{info.get("channel","")}__:\n**{info.get("title","")}**"""
|
||||
await asyncio.to_thread(yt_obj.download, self.url)
|
||||
|
||||
if "youtu" in self.url:
|
||||
self.caption = (
|
||||
f"""__{info.get("channel","")}__:\n**{info.get("title","")}**"""
|
||||
)
|
||||
|
||||
if os.path.isfile(self.video_path):
|
||||
self.link = self.video_path
|
||||
self.thumb = await take_ss(self.video_path, path=self.path)
|
||||
self.video = self.success = True
|
||||
|
||||
def check_url(self):
|
||||
if "youtu" in self.url and (
|
||||
"/live" in self.url or os.path.basename(self.url).startswith("@")
|
||||
):
|
||||
return 1
|
||||
|
||||
def set_format(self):
|
||||
if "/shorts" in self.url:
|
||||
self._opts["format"] = "bv[ext=mp4][res=720]+ba[ext=m4a]/b[ext=mp4]"
|
||||
elif "youtu" in self.url:
|
||||
self._opts["format"] = "bv[ext=mp4][res=480]+ba[ext=m4a]/b[ext=mp4]"
|
||||
else:
|
||||
self._opts["format"] = "b[ext=mp4]"
|
||||
|
@ -1,14 +1,15 @@
|
||||
import os
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
class Config:
|
||||
API_KEYS = json.loads(os.environ.get("API_KEYS", "[]"))
|
||||
|
||||
BLOCKED_USERS = []
|
||||
BLOCKED_USERS_MESSAGE_ID = int(os.environ.get("BLOCKED_USERS_MESSAGE_ID",0))
|
||||
BLOCKED_USERS_MESSAGE_ID = int(os.environ.get("BLOCKED_USERS_MESSAGE_ID", 0))
|
||||
|
||||
CHATS = []
|
||||
AUTO_DL_MESSAGE_ID = int(os.environ.get("AUTO_DL_MESSAGE_ID",0))
|
||||
AUTO_DL_MESSAGE_ID = int(os.environ.get("AUTO_DL_MESSAGE_ID", 0))
|
||||
|
||||
CMD_DICT = {}
|
||||
|
||||
@ -17,4 +18,4 @@ class Config:
|
||||
TRIGGER = os.environ.get("TRIGGER", ".")
|
||||
|
||||
USERS = []
|
||||
USERS_MESSAGE_ID = int(os.environ.get("USERS_MESSAGE_ID",0))
|
||||
USERS_MESSAGE_ID = int(os.environ.get("USERS_MESSAGE_ID", 0))
|
||||
|
@ -4,6 +4,9 @@ import os
|
||||
import traceback
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from pyrogram.errors import MediaEmpty, PhotoSaveFileInvalid, WebpageCurlFailed
|
||||
from pyrogram.types import InputMediaPhoto, InputMediaVideo
|
||||
|
||||
from app.api.gallerydl import Gallery_DL
|
||||
from app.api.instagram import Instagram
|
||||
from app.api.reddit import Reddit
|
||||
@ -11,8 +14,6 @@ from app.api.threads import Threads
|
||||
from app.api.tiktok import Tiktok
|
||||
from app.api.ytdl import YT_DL
|
||||
from app.core import aiohttp_tools, shell
|
||||
from pyrogram.errors import MediaEmpty, PhotoSaveFileInvalid, WebpageCurlFailed
|
||||
from pyrogram.types import InputMediaPhoto, InputMediaVideo
|
||||
|
||||
url_map = {
|
||||
"tiktok.com": Tiktok,
|
||||
@ -29,32 +30,48 @@ url_map = {
|
||||
|
||||
class ExtractAndSendMedia:
|
||||
def __init__(self, message):
|
||||
self.exceptions, self.media_objects = [], []
|
||||
self.exceptions, self.media_objects, self.sender_dict = [], [], {}
|
||||
self.__client = message._client
|
||||
self.message = message
|
||||
self.doc = "-d" in message.flags
|
||||
self.spoiler = "-s" in message.flags
|
||||
self.sender = "" if "-ns" in message.flags else f"\nShared by : {self.extract_sender()}"
|
||||
self.args_ = {
|
||||
"chat_id": self.message.chat.id,
|
||||
"reply_to_message_id": message.reply_id,
|
||||
}
|
||||
|
||||
def extract_sender(self):
|
||||
def get_sender(self, reply=False):
|
||||
if "-ns" in self.message.flags:
|
||||
return ""
|
||||
text = f"\nShared by : "
|
||||
author = self.message.author_signature
|
||||
sender = user.first_name if (user := self.message.from_user) else ""
|
||||
return author or sender
|
||||
reply_sender = ""
|
||||
if reply:
|
||||
reply_msg = self.message.replied
|
||||
reply_sender = (
|
||||
reply_user.first_name if (reply_user := reply_msg.from_user) else ""
|
||||
)
|
||||
if any((author, sender, reply_sender)):
|
||||
return text + (author or sender if not reply else reply_sender)
|
||||
else:
|
||||
return ""
|
||||
|
||||
async def get_media(self):
|
||||
async with asyncio.TaskGroup() as task_group:
|
||||
tasks = []
|
||||
for link in self.message.get_text_list:
|
||||
text_list = self.message.text_list
|
||||
reply_text_list = self.message.reply_text_list
|
||||
for link in text_list + reply_text_list:
|
||||
reply = link in reply_text_list
|
||||
if match := url_map.get(urlparse(link).netloc):
|
||||
tasks.append(task_group.create_task(match.start(link)))
|
||||
self.sender_dict[link] = self.get_sender(reply=reply)
|
||||
else:
|
||||
for key, val in url_map.items():
|
||||
if key in link:
|
||||
tasks.append(task_group.create_task(val.start(link)))
|
||||
self.sender_dict[link] = self.get_sender(reply=reply)
|
||||
self.media_objects = [task.result() for task in tasks if task.result()]
|
||||
|
||||
async def send_media(self):
|
||||
@ -62,7 +79,9 @@ class ExtractAndSendMedia:
|
||||
if "-nc" in self.message.flags:
|
||||
caption = ""
|
||||
else:
|
||||
caption = obj.caption + obj.caption_url + self.sender
|
||||
caption = (
|
||||
obj.caption + obj.caption_url + self.sender_dict[obj.query_url]
|
||||
)
|
||||
try:
|
||||
if self.doc:
|
||||
await self.send_document(obj.link, caption=caption, path=obj.path)
|
||||
@ -70,14 +89,14 @@ class ExtractAndSendMedia:
|
||||
await self.send_group(obj, caption=caption)
|
||||
elif obj.photo:
|
||||
await self.send(
|
||||
media={"photo":obj.link},
|
||||
media={"photo": obj.link},
|
||||
method=self.__client.send_photo,
|
||||
caption=caption,
|
||||
has_spoiler=self.spoiler,
|
||||
)
|
||||
elif obj.video:
|
||||
await self.send(
|
||||
media={"video":obj.link},
|
||||
media={"video": obj.link},
|
||||
method=self.__client.send_video,
|
||||
thumb=await aiohttp_tools.thumb_dl(obj.thumb),
|
||||
caption=caption,
|
||||
@ -85,14 +104,16 @@ class ExtractAndSendMedia:
|
||||
)
|
||||
elif obj.gif:
|
||||
await self.send(
|
||||
media={"animation":obj.link},
|
||||
media={"animation": obj.link},
|
||||
method=self.__client.send_animation,
|
||||
caption=caption,
|
||||
has_spoiler=self.spoiler,
|
||||
unsave=True,
|
||||
)
|
||||
except BaseException:
|
||||
self.exceptions.append("\n".join([obj.caption_url.strip(), traceback.format_exc()]))
|
||||
self.exceptions.append(
|
||||
"\n".join([obj.caption_url.strip(), traceback.format_exc()])
|
||||
)
|
||||
|
||||
async def send(self, media, method, **kwargs):
|
||||
try:
|
||||
@ -103,20 +124,28 @@ class ExtractAndSendMedia:
|
||||
media[key] = await aiohttp_tools.in_memory_dl(value)
|
||||
await method(**media, **self.args_, **kwargs)
|
||||
except PhotoSaveFileInvalid:
|
||||
await self.__client.send_document(**self.args_, document=media, caption=caption, force_document=True)
|
||||
await self.__client.send_document(
|
||||
**self.args_, document=media, caption=caption, force_document=True
|
||||
)
|
||||
|
||||
async def send_document(self, docs, caption, path=""):
|
||||
if not path:
|
||||
docs = await asyncio.gather(*[aiohttp_tools.in_memory_dl(doc) for doc in docs])
|
||||
docs = await asyncio.gather(
|
||||
*[aiohttp_tools.in_memory_dl(doc) for doc in docs]
|
||||
)
|
||||
else:
|
||||
[os.rename(file_, file_ + ".png") for file_ in glob.glob(f"{path}/*.webp")]
|
||||
docs = glob.glob(f"{path}/*")
|
||||
for doc in docs:
|
||||
try:
|
||||
await self.__client.send_document(**self.args_, document=doc, caption=caption, force_document=True)
|
||||
await self.__client.send_document(
|
||||
**self.args_, document=doc, caption=caption, force_document=True
|
||||
)
|
||||
except (MediaEmpty, WebpageCurlFailed):
|
||||
doc = await aiohttp_tools.in_memory_dl(doc)
|
||||
await self.__client.send_document(**self.args_, document=doc, caption=caption, force_document=True)
|
||||
await self.__client.send_document(
|
||||
**self.args_, document=doc, caption=caption, force_document=True
|
||||
)
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
async def send_group(self, media, caption):
|
||||
@ -128,7 +157,13 @@ class ExtractAndSendMedia:
|
||||
if isinstance(data, list):
|
||||
await self.__client.send_media_group(**self.args_, media=data)
|
||||
else:
|
||||
await self.send(media={"animation": data}, method=self.__client.send_animation, caption=caption, has_spoiler=self.spoiler, unsave=True)
|
||||
await self.send(
|
||||
media={"animation": data},
|
||||
method=self.__client.send_animation,
|
||||
caption=caption,
|
||||
has_spoiler=self.spoiler,
|
||||
unsave=True,
|
||||
)
|
||||
await asyncio.sleep(1)
|
||||
|
||||
async def sort_media_path(self, path, caption):
|
||||
@ -136,24 +171,34 @@ class ExtractAndSendMedia:
|
||||
images, videos, animations = [], [], []
|
||||
for file in glob.glob(f"{path}/*"):
|
||||
if file.lower().endswith((".png", ".jpg", ".jpeg")):
|
||||
images.append(InputMediaPhoto(file, caption=caption, has_spoiler=self.spoiler))
|
||||
images.append(
|
||||
InputMediaPhoto(file, caption=caption, has_spoiler=self.spoiler)
|
||||
)
|
||||
if file.lower().endswith((".mp4", ".mkv", ".webm")):
|
||||
has_audio = await shell.check_audio(file)
|
||||
if not has_audio:
|
||||
animations.append(file)
|
||||
else:
|
||||
videos.append(InputMediaVideo(file, caption=caption, has_spoiler=self.spoiler))
|
||||
videos.append(
|
||||
InputMediaVideo(file, caption=caption, has_spoiler=self.spoiler)
|
||||
)
|
||||
return await self.make_chunks(images, videos, animations)
|
||||
|
||||
async def sort_media_urls(self, urls, caption):
|
||||
images, videos, animations = [], [], []
|
||||
downloads = await asyncio.gather(*[aiohttp_tools.in_memory_dl(url) for url in urls])
|
||||
downloads = await asyncio.gather(
|
||||
*[aiohttp_tools.in_memory_dl(url) for url in urls]
|
||||
)
|
||||
for file_obj in downloads:
|
||||
name = file_obj.name.lower()
|
||||
if name.endswith((".png", ".jpg", ".jpeg")):
|
||||
images.append(InputMediaPhoto(file_obj, caption=caption, has_spoiler=self.spoiler))
|
||||
images.append(
|
||||
InputMediaPhoto(file_obj, caption=caption, has_spoiler=self.spoiler)
|
||||
)
|
||||
if name.endswith((".mp4", ".mkv", ".webm")):
|
||||
videos.append(InputMediaVideo(file_obj, caption=caption, has_spoiler=self.spoiler))
|
||||
videos.append(
|
||||
InputMediaVideo(file_obj, caption=caption, has_spoiler=self.spoiler)
|
||||
)
|
||||
if name.endswith(".gif"):
|
||||
animations.append(file_obj)
|
||||
return await self.make_chunks(images, videos, animations)
|
||||
|
@ -15,9 +15,17 @@ async def session_switch():
|
||||
await SESSION.close()
|
||||
|
||||
|
||||
async def get_json(url: str, headers: dict = None, params: dict = None, json_: bool = False, timeout: int = 10):
|
||||
async def get_json(
|
||||
url: str,
|
||||
headers: dict = None,
|
||||
params: dict = None,
|
||||
json_: bool = False,
|
||||
timeout: int = 10,
|
||||
):
|
||||
try:
|
||||
async with SESSION.get(url=url, headers=headers, params=params, timeout=timeout) as ses:
|
||||
async with SESSION.get(
|
||||
url=url, headers=headers, params=params, timeout=timeout
|
||||
) as ses:
|
||||
if json_:
|
||||
ret_json = await ses.json()
|
||||
else:
|
||||
|
@ -11,17 +11,15 @@ from pyrogram.enums import ParseMode
|
||||
|
||||
from app import Config
|
||||
from app.core import aiohttp_tools
|
||||
|
||||
from app.core.message import Message
|
||||
|
||||
|
||||
class BOT(Client):
|
||||
|
||||
def __init__(self):
|
||||
if string := os.environ.get("STRING_SESSION"):
|
||||
mode_arg = { "session_string": string }
|
||||
mode_arg = {"session_string": string}
|
||||
else:
|
||||
mode_arg = { "bot_token": os.environ.get("BOT_TOKEN") }
|
||||
mode_arg = {"bot_token": os.environ.get("BOT_TOKEN")}
|
||||
super().__init__(
|
||||
name="bot",
|
||||
**mode_arg,
|
||||
@ -60,7 +58,11 @@ class BOT(Client):
|
||||
restart_chat = os.environ.get("RESTART_CHAT")
|
||||
if restart_msg and restart_chat:
|
||||
await super().get_chat(int(restart_chat))
|
||||
await super().edit_message_text(chat_id=int(restart_chat), message_id=int(restart_msg), text="#Social-dl\n__Started__")
|
||||
await super().edit_message_text(
|
||||
chat_id=int(restart_chat),
|
||||
message_id=int(restart_msg),
|
||||
text="#Social-dl\n__Started__",
|
||||
)
|
||||
os.environ.pop("RESTART_MSG", "")
|
||||
os.environ.pop("RESTART_CHAT", "")
|
||||
|
||||
@ -70,10 +72,17 @@ class BOT(Client):
|
||||
py_name = name.replace("/", ".")
|
||||
importlib.import_module(py_name)
|
||||
|
||||
async def log(self, text, chat=None, func=None, name="log.txt",disable_web_page_preview=True):
|
||||
async def log(
|
||||
self, text, chat=None, func=None, name="log.txt", disable_web_page_preview=True
|
||||
):
|
||||
if chat or func:
|
||||
text = f"<b>Function:</b> {func}\n<b>Chat:</b> {chat}\n<b>Traceback:</b>\n{text}"
|
||||
return await self.send_message(chat_id=Config.LOG_CHAT, text=text, name=name, disable_web_page_preview=disable_web_page_preview)
|
||||
return await self.send_message(
|
||||
chat_id=Config.LOG_CHAT,
|
||||
text=text,
|
||||
name=name,
|
||||
disable_web_page_preview=disable_web_page_preview,
|
||||
)
|
||||
|
||||
async def restart(self):
|
||||
await aiohttp_tools.session_switch()
|
||||
@ -86,16 +95,23 @@ class BOT(Client):
|
||||
users = Config.USERS_MESSAGE_ID
|
||||
|
||||
if chats_id:
|
||||
Config.CHATS = json.loads((await super().get_messages(Config.LOG_CHAT, chats_id)).text)
|
||||
Config.CHATS = json.loads(
|
||||
(await super().get_messages(Config.LOG_CHAT, chats_id)).text
|
||||
)
|
||||
if blocked_id:
|
||||
Config.BLOCKED_USERS = json.loads((await super().get_messages(Config.LOG_CHAT, blocked_id)).text)
|
||||
Config.BLOCKED_USERS = json.loads(
|
||||
(await super().get_messages(Config.LOG_CHAT, blocked_id)).text
|
||||
)
|
||||
if users:
|
||||
Config.USERS = json.loads((await super().get_messages(Config.LOG_CHAT, users)).text)
|
||||
|
||||
Config.USERS = json.loads(
|
||||
(await super().get_messages(Config.LOG_CHAT, users)).text
|
||||
)
|
||||
|
||||
async def send_message(self, chat_id, text, name: str = "output.txt", **kwargs):
|
||||
if len(str(text)) < 4096:
|
||||
return Message.parse_message((await super().send_message(chat_id=chat_id, text=text, **kwargs)))
|
||||
return Message.parse_message(
|
||||
(await super().send_message(chat_id=chat_id, text=text, **kwargs))
|
||||
)
|
||||
doc = BytesIO(bytes(text, encoding="utf-8"))
|
||||
doc.name = name
|
||||
kwargs.pop("disable_web_page_preview", "")
|
||||
|
@ -15,7 +15,7 @@ def Dynamic_Chat_Filter(_, __, message):
|
||||
):
|
||||
return False
|
||||
user = message.from_user
|
||||
if user and ( user.id in Config.BLOCKED_USERS or user.is_bot ):
|
||||
if user and (user.id in Config.BLOCKED_USERS or user.is_bot):
|
||||
return False
|
||||
url_check = check_for_urls(message.text.split())
|
||||
return bool(url_check)
|
||||
|
@ -1,58 +1,102 @@
|
||||
import asyncio
|
||||
from functools import cached_property
|
||||
|
||||
from pyrogram.types import Message as MSG
|
||||
|
||||
from app import Config
|
||||
|
||||
|
||||
class Message(MSG):
|
||||
def __init__(self, message):
|
||||
self.flags = []
|
||||
self.input, self.flt_input = "", ""
|
||||
self.replied, self.reply_id = None, None
|
||||
super().__dict__.update(message.__dict__)
|
||||
self.set_reply_properties()
|
||||
self.flags_n_input()
|
||||
self.set_flt_input()
|
||||
|
||||
@property
|
||||
def get_text_list(self):
|
||||
text_list = self.text.split()
|
||||
if self.replied and (reply_text := self.replied.text) and "dl" in text_list[0]:
|
||||
text_list.extend(reply_text.split())
|
||||
return text_list
|
||||
@cached_property
|
||||
def text_list(self):
|
||||
return self.text.split()
|
||||
|
||||
def set_reply_properties(self):
|
||||
if replied := self.reply_to_message:
|
||||
self.replied = replied
|
||||
self.reply_id = replied.id
|
||||
@cached_property
|
||||
def reply_text_list(self):
|
||||
reply_text_list = []
|
||||
if (
|
||||
self.replied
|
||||
and (reply_text := self.replied.text)
|
||||
and "dl" in self.text_list[0]
|
||||
):
|
||||
reply_text_list = self.replied.text_list
|
||||
return reply_text_list
|
||||
|
||||
def flags_n_input(self):
|
||||
self.flags = [i for i in self.text.split() if i.startswith("-") ]
|
||||
split_cmd_str = self.text.split(maxsplit=1)
|
||||
if len(split_cmd_str) > 1:
|
||||
self.input = split_cmd_str[-1]
|
||||
@cached_property
|
||||
def cmd(self):
|
||||
raw_cmd = self.text_list[0]
|
||||
cmd = raw_cmd.lstrip(Config.TRIGGER)
|
||||
return cmd if cmd in Config.CMD_DICT else None
|
||||
|
||||
def set_flt_input(self):
|
||||
line_split = self.input.splitlines()
|
||||
split_n_joined =[
|
||||
@cached_property
|
||||
def flags(self):
|
||||
return [i for i in self.text_list if i.startswith("-")]
|
||||
|
||||
@cached_property
|
||||
def input(self):
|
||||
if len(self.text_list) > 1:
|
||||
return self.text.split(maxsplit=1)[-1]
|
||||
return ""
|
||||
|
||||
@cached_property
|
||||
def flt_input(self):
|
||||
split_lines = self.input.splitlines()
|
||||
split_n_joined = [
|
||||
" ".join([word for word in line.split(" ") if word not in self.flags])
|
||||
for line in line_split
|
||||
for line in split_lines
|
||||
]
|
||||
self.flt_input = "\n".join(split_n_joined)
|
||||
return "\n".join(split_n_joined)
|
||||
|
||||
async def reply(self, text, **kwargs):
|
||||
return await self._client.send_message(chat_id=self.chat.id, text=text, reply_to_message_id=self.id, **kwargs)
|
||||
@cached_property
|
||||
def replied(self):
|
||||
if self.reply_to_message:
|
||||
return Message.parse_message(self.reply_to_message)
|
||||
|
||||
async def edit(self, text, **kwargs):
|
||||
@cached_property
|
||||
def reply_id(self):
|
||||
return self.replied.id if self.replied else None
|
||||
|
||||
async def reply(self, text, del_in: int = 0, block=True, **kwargs):
|
||||
task = self._client.send_message(
|
||||
chat_id=self.chat.id, text=text, reply_to_message_id=self.id, **kwargs
|
||||
)
|
||||
if del_in:
|
||||
await self.async_deleter(task=task, del_in=del_in, block=block)
|
||||
else:
|
||||
return await task
|
||||
|
||||
async def edit(self, text, del_in: int = 0, block=True, **kwargs):
|
||||
if len(str(text)) < 4096:
|
||||
kwargs.pop("name", "")
|
||||
await self.edit_text(text, **kwargs)
|
||||
task = self.edit_text(text, **kwargs)
|
||||
if del_in:
|
||||
reply = await self.async_deleter(task=task, del_in=del_in, block=block)
|
||||
else:
|
||||
reply = await task
|
||||
else:
|
||||
await super().delete()
|
||||
return await self.reply(text, **kwargs)
|
||||
_, reply = await asyncio.gather(
|
||||
super().delete(), self.reply(text, **kwargs)
|
||||
)
|
||||
return reply
|
||||
|
||||
async def delete(self, reply=False):
|
||||
await super().delete()
|
||||
if reply and self.replied:
|
||||
await self.replied.delete()
|
||||
|
||||
async def async_deleter(self, del_in, task, block):
|
||||
if block:
|
||||
x = await task
|
||||
await asyncio.sleep(del_in)
|
||||
await x.delete()
|
||||
else:
|
||||
asyncio.create_task(
|
||||
self.async_deleter(del_in=del_in, task=task, block=True)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def parse_message(cls, message):
|
||||
ret_obj = cls(message)
|
||||
|
@ -14,12 +14,14 @@ class ScraperConfig:
|
||||
self.group = False
|
||||
self.gif = False
|
||||
|
||||
def set_sauce(self, url):
|
||||
self.caption_url = f"\n\n<a href='{url}'>Sauce</a>"
|
||||
def set_sauce(self):
|
||||
self.caption_url = f"\n\n<a href='{self.query_url}'>Sauce</a>"
|
||||
|
||||
@classmethod
|
||||
async def start(cls, url):
|
||||
obj = cls(url=url)
|
||||
obj.query_url = url
|
||||
obj.set_sauce()
|
||||
await obj.download_or_extract()
|
||||
if obj.success:
|
||||
return obj
|
||||
|
@ -4,18 +4,24 @@ import os
|
||||
|
||||
async def take_ss(video: str, path: str):
|
||||
thumb = f"{path}/i.png"
|
||||
await run_shell_cmd(f'''ffmpeg -hide_banner -loglevel error -ss 0.1 -i "{video}" -vframes 1 "{thumb}"''')
|
||||
await run_shell_cmd(
|
||||
f'''ffmpeg -hide_banner -loglevel error -ss 0.1 -i "{video}" -vframes 1 "{thumb}"'''
|
||||
)
|
||||
if os.path.isfile(thumb):
|
||||
return thumb
|
||||
|
||||
|
||||
async def check_audio(file):
|
||||
result = await run_shell_cmd(f"ffprobe -v error -show_entries format=nb_streams -of default=noprint_wrappers=1:nokey=1 {file}")
|
||||
result = await run_shell_cmd(
|
||||
f"ffprobe -v error -show_entries format=nb_streams -of default=noprint_wrappers=1:nokey=1 {file}"
|
||||
)
|
||||
return int(result or 0) - 1
|
||||
|
||||
|
||||
async def run_shell_cmd(cmd):
|
||||
proc = await asyncio.create_subprocess_shell(cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT)
|
||||
proc = await asyncio.create_subprocess_shell(
|
||||
cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT
|
||||
)
|
||||
stdout, _ = await proc.communicate()
|
||||
return stdout.decode("utf-8")
|
||||
|
||||
@ -41,7 +47,11 @@ class AsyncShell:
|
||||
@classmethod
|
||||
async def run_cmd(cls, cmd):
|
||||
# Create Subprocess and initialise self using cls
|
||||
sub_process = cls(process=await asyncio.create_subprocess_shell(cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT))
|
||||
sub_process = cls(
|
||||
process=await asyncio.create_subprocess_shell(
|
||||
cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT
|
||||
)
|
||||
)
|
||||
# Start Checking output but don't block code by awaiting it.
|
||||
asyncio.create_task(sub_process.get_output())
|
||||
# Sleep for a short time to let previous task start
|
||||
|
@ -61,8 +61,8 @@ async def add_sudo(bot, message):
|
||||
config_list=Config.USERS,
|
||||
message_id=Config.USERS_MESSAGE_ID,
|
||||
):
|
||||
return await message.reply(err)
|
||||
await message.reply("User Added to Authorised List.")
|
||||
return await message.reply(err, del_in=5)
|
||||
await message.reply("User Added to Authorised List.", del_in=5)
|
||||
|
||||
|
||||
@bot.add_cmd(cmd="delsudo")
|
||||
@ -77,8 +77,8 @@ async def add_sudo(bot, message):
|
||||
config_list=Config.USERS,
|
||||
message_id=Config.USERS_MESSAGE_ID,
|
||||
):
|
||||
return await message.reply(err)
|
||||
await message.reply("User Removed from Authorised List.")
|
||||
return await message.reply(err, del_in=5)
|
||||
await message.reply("User Removed from Authorised List.", del_in=5)
|
||||
|
||||
|
||||
@bot.add_cmd(cmd="addchat")
|
||||
@ -93,8 +93,11 @@ async def add_chat(bot, message):
|
||||
config_list=Config.CHATS,
|
||||
message_id=Config.AUTO_DL_MESSAGE_ID,
|
||||
):
|
||||
return await message.reply(err)
|
||||
await message.reply(f"<b>{message.chat.title or message.chat.first_name}</b> Added to Authorised List.")
|
||||
return await message.reply(err, del_in=5)
|
||||
await message.reply(
|
||||
f"<b>{message.chat.title or message.chat.first_name}</b> Added to Authorised List.",
|
||||
del_in=5,
|
||||
)
|
||||
|
||||
|
||||
@bot.add_cmd(cmd="delchat")
|
||||
@ -109,9 +112,11 @@ async def add_chat(bot, message):
|
||||
config_list=Config.CHATS,
|
||||
message_id=Config.AUTO_DL_MESSAGE_ID,
|
||||
):
|
||||
return await message.reply(err)
|
||||
await message.reply(f"<b>{message.chat.title or message.chat.first_name}</b> Added Removed from Authorised List.")
|
||||
|
||||
return await message.reply(err, del_in=5)
|
||||
await message.reply(
|
||||
f"<b>{message.chat.title or message.chat.first_name}</b> Added Removed from Authorised List.",
|
||||
del_in=5,
|
||||
)
|
||||
|
||||
|
||||
@bot.add_cmd(cmd="block")
|
||||
@ -126,8 +131,8 @@ async def add_sudo(bot, message):
|
||||
config_list=Config.BLOCKED_USERS,
|
||||
message_id=Config.BLOCKED_USERS_MESSAGE_ID,
|
||||
):
|
||||
return await message.reply(err)
|
||||
await message.reply("User Added to Ban List.")
|
||||
return await message.reply(err, del_in=5)
|
||||
await message.reply("User Added to Ban List.", del_in=5)
|
||||
|
||||
|
||||
@bot.add_cmd(cmd="unblock")
|
||||
@ -142,8 +147,5 @@ async def add_sudo(bot, message):
|
||||
config_list=Config.BLOCKED_USERS,
|
||||
message_id=Config.BLOCKED_USERS_MESSAGE_ID,
|
||||
):
|
||||
return await message.reply(err)
|
||||
await message.reply("User Removed from Ban List.")
|
||||
|
||||
|
||||
|
||||
return await message.reply(err, del_in=5)
|
||||
await message.reply("User Removed from Ban List.", del_in=5)
|
||||
|
@ -8,14 +8,23 @@ from app import Config, bot
|
||||
@bot.add_cmd(cmd="bot")
|
||||
async def info(bot, message):
|
||||
head = "<b><a href=https://t.me/Social_DL>Social-DL</a> is running.</b>"
|
||||
chat_count = f"\n<b>Auto-Dl enabled in: <code>{len(Config.CHATS)}</code> chats</b>\n"
|
||||
chat_count = (
|
||||
f"\n<b>Auto-Dl enabled in: <code>{len(Config.CHATS)}</code> chats</b>\n"
|
||||
)
|
||||
supported_sites, photo = await bot.get_messages("Social_DL", [2, 3])
|
||||
await photo.copy(message.chat.id, caption="\n".join([head, chat_count, supported_sites.text.html]))
|
||||
await photo.copy(
|
||||
message.chat.id,
|
||||
caption="\n".join([head, chat_count, supported_sites.text.html]),
|
||||
)
|
||||
|
||||
|
||||
@bot.add_cmd(cmd="help")
|
||||
async def help(bot, message):
|
||||
commands = "\n".join([ f"<code>{Config.TRIGGER}{i}</code>" for i in Config.CMD_DICT.keys()])
|
||||
await message.reply(f"<b>Available Commands:</b>\n\n{commands}")
|
||||
commands = "\n".join(
|
||||
[f"<code>{Config.TRIGGER}{i}</code>" for i in Config.CMD_DICT.keys()]
|
||||
)
|
||||
await message.reply(f"<b>Available Commands:</b>\n\n{commands}", del_in=30)
|
||||
|
||||
|
||||
@bot.add_cmd(cmd="restart")
|
||||
async def restart(bot, message):
|
||||
@ -29,4 +38,4 @@ async def restart(bot, message):
|
||||
@bot.add_cmd(cmd="update")
|
||||
async def chat_update(bot, message):
|
||||
await bot.set_filter_list()
|
||||
await message.reply("Filters Refreshed")
|
||||
await message.reply("Filters Refreshed", del_in=10)
|
||||
|
109
app/plugins/dev_tools.py
Normal file
109
app/plugins/dev_tools.py
Normal file
@ -0,0 +1,109 @@
|
||||
import asyncio
|
||||
import importlib
|
||||
import sys
|
||||
import traceback
|
||||
from io import StringIO
|
||||
|
||||
from pyrogram.enums import ParseMode
|
||||
|
||||
from app import Config
|
||||
from app.core import shell
|
||||
|
||||
from app.core import aiohttp_tools as aio # isort:skip
|
||||
|
||||
|
||||
# Run shell commands
|
||||
async def run_cmd(bot, message):
|
||||
cmd = message.input.strip()
|
||||
status_ = await message.reply("executing...")
|
||||
proc_stdout = await shell.run_shell_cmd(cmd)
|
||||
output = f"`${cmd}`\n\n`{proc_stdout}`"
|
||||
return await status_.edit(output, name="sh.txt", disable_web_page_preview=True)
|
||||
|
||||
|
||||
# Shell but Live Output
|
||||
async def live_shell(bot, message):
|
||||
cmd = message.input.strip()
|
||||
sub_process = await shell.AsyncShell.run_cmd(cmd)
|
||||
reply = await message.reply("`getting live output....`")
|
||||
output = ""
|
||||
sleep_for = 1
|
||||
while sub_process.is_not_completed:
|
||||
# Edit message only when there's new output.
|
||||
if output != sub_process.full_std:
|
||||
output = sub_process.full_std
|
||||
if len(output) <= 4096:
|
||||
await reply.edit(
|
||||
f"`{output}`",
|
||||
disable_web_page_preview=True,
|
||||
parse_mode=ParseMode.MARKDOWN,
|
||||
)
|
||||
# Reset sleep duration
|
||||
if sleep_for >= 5:
|
||||
sleep_for = 1
|
||||
# Sleep to Unblock running loop and let output reader read new
|
||||
# output.
|
||||
await asyncio.sleep(sleep_for)
|
||||
sleep_for += 1
|
||||
# If the subprocess is finished edit the message with cmd and full
|
||||
# output
|
||||
return await reply.edit(
|
||||
f"`$ {cmd}\n\n``{sub_process.full_std}`",
|
||||
name="shell.txt",
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
|
||||
|
||||
# Run Python code
|
||||
async def executor(bot, message):
|
||||
code = message.flt_input.strip()
|
||||
if not code:
|
||||
return await message.reply("exec Jo mama?")
|
||||
reply = await message.reply("executing")
|
||||
sys.stdout = codeOut = StringIO()
|
||||
sys.stderr = codeErr = StringIO()
|
||||
# Indent code as per proper python syntax
|
||||
formatted_code = "\n ".join(code.splitlines())
|
||||
try:
|
||||
# Create and initialise the function
|
||||
exec(f"async def _exec(bot, message):\n {formatted_code}")
|
||||
func_out = await locals()["_exec"](bot, message)
|
||||
except BaseException:
|
||||
func_out = str(traceback.format_exc())
|
||||
sys.stdout = sys.__stdout__
|
||||
sys.stderr = sys.__stderr__
|
||||
output = f"`{codeOut.getvalue().strip() or codeErr.getvalue().strip() or func_out}`"
|
||||
if "-s" not in message.flags:
|
||||
output = f"> `{code}`\n\n>> {output}"
|
||||
return await reply.edit(
|
||||
output,
|
||||
name="exec.txt",
|
||||
disable_web_page_preview=True,
|
||||
parse_mode=ParseMode.MARKDOWN,
|
||||
)
|
||||
|
||||
|
||||
async def loader(bot, message):
|
||||
if (
|
||||
not message.replied
|
||||
or not message.replied.document
|
||||
or not message.replied.document.file_name.endswith(".py")
|
||||
):
|
||||
return await message.reply("reply to a plugin.")
|
||||
reply = await message.reply("Loading....")
|
||||
file_name = message.replied.document.file_name.rstrip(".py")
|
||||
reload = sys.modules.pop(f"app.temp.{file_name}", None)
|
||||
status = "Reloaded" if reload else "Loaded"
|
||||
await message.replied.download("app/temp/")
|
||||
try:
|
||||
importlib.import_module(f"app.temp.{file_name}")
|
||||
except BaseException:
|
||||
return await reply.edit(str(traceback.format_exc()))
|
||||
await reply.edit(f"{status} {file_name}.py.")
|
||||
|
||||
|
||||
if Config.DEV_MODE:
|
||||
Config.CMD_DICT["sh"] = run_cmd
|
||||
Config.CMD_DICT["shell"] = live_shell
|
||||
Config.CMD_DICT["exec"] = executor
|
||||
Config.CMD_DICT["load"] = loader
|
@ -1,24 +0,0 @@
|
||||
import importlib
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from app import bot
|
||||
|
||||
@bot.add_cmd(cmd="load")
|
||||
async def loader(bot, message):
|
||||
if (
|
||||
not message.replied
|
||||
or not message.replied.document
|
||||
or not message.replied.document.file_name.endswith(".py")
|
||||
):
|
||||
return await message.reply("reply to a plugin.")
|
||||
reply = await message.reply("Loading....")
|
||||
file_name = message.replied.document.file_name.rstrip(".py")
|
||||
reload = sys.modules.pop(f"app.temp.{file_name}", None)
|
||||
status = "Reloaded" if reload else "Loaded"
|
||||
plugin = await message.replied.download("app/temp/")
|
||||
try:
|
||||
importlib.import_module(f"app.temp.{file_name}")
|
||||
except BaseException:
|
||||
return await reply.edit(str(traceback.format_exc()))
|
||||
await reply.edit(f"{status} {file_name}.py.")
|
@ -5,11 +5,19 @@ from time import time
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import yt_dlp
|
||||
|
||||
from app import bot
|
||||
from app.api.ytdl import FakeLogger
|
||||
from app.core.aiohttp_tools import in_memory_dl
|
||||
|
||||
domains = ["www.youtube.com", "youtube.com", "m.youtube.com", "youtu.be", "www.youtube-nocookie.com", "music.youtube.com"]
|
||||
domains = [
|
||||
"www.youtube.com",
|
||||
"youtube.com",
|
||||
"m.youtube.com",
|
||||
"youtu.be",
|
||||
"www.youtube-nocookie.com",
|
||||
"music.youtube.com",
|
||||
]
|
||||
|
||||
|
||||
@bot.add_cmd(cmd="song")
|
||||
@ -36,7 +44,11 @@ async def song_dl(bot, message):
|
||||
"logger": FakeLogger(),
|
||||
"outtmpl": dl_path + "%(title)s.%(ext)s",
|
||||
"format": "bestaudio",
|
||||
"postprocessors": [{"key": "FFmpegExtractAudio", "preferredcodec": aformat}, {"key": "FFmpegMetadata"}, {"key": "EmbedThumbnail"}],
|
||||
"postprocessors": [
|
||||
{"key": "FFmpegExtractAudio", "preferredcodec": aformat},
|
||||
{"key": "FFmpegMetadata"},
|
||||
{"key": "EmbedThumbnail"},
|
||||
],
|
||||
}
|
||||
ytdl = yt_dlp.YoutubeDL(yt_opts)
|
||||
yt_info = await asyncio.to_thread(ytdl.extract_info, query_or_search)
|
||||
@ -51,6 +63,11 @@ async def song_dl(bot, message):
|
||||
await response.edit("Uploading....")
|
||||
for audio_file in down_path:
|
||||
if audio_file.endswith((".opus", ".mp3")):
|
||||
await message.reply_audio(audio=audio_file, duration=int(duration), performer=str(artist), thumb=thumb)
|
||||
await message.reply_audio(
|
||||
audio=audio_file,
|
||||
duration=int(duration),
|
||||
performer=str(artist),
|
||||
thumb=thumb,
|
||||
)
|
||||
await response.delete()
|
||||
shutil.rmtree(dl_path, ignore_errors=True)
|
@ -23,7 +23,9 @@ async def purge_(bot, message: Message):
|
||||
start_message = reply.id
|
||||
end_message = message.id
|
||||
messages = [end_message] + [i for i in range(int(start_message), int(end_message))]
|
||||
await bot.delete_messages(chat_id=message.chat.id, message_ids=messages, revoke=True)
|
||||
await bot.delete_messages(
|
||||
chat_id=message.chat.id, message_ids=messages, revoke=True
|
||||
)
|
||||
|
||||
|
||||
@bot.add_cmd(cmd="ids")
|
||||
@ -70,4 +72,9 @@ async def leave_chat(bot, message):
|
||||
@bot.add_cmd(cmd="reply")
|
||||
async def reply(bot, message):
|
||||
text = message.input
|
||||
await bot.send_message(chat_id=message.chat.id, text=text, reply_to_message_id=message.reply_id, disable_web_page_preview=True)
|
||||
await bot.send_message(
|
||||
chat_id=message.chat.id,
|
||||
text=text,
|
||||
reply_to_message_id=message.reply_id,
|
||||
disable_web_page_preview=True,
|
||||
)
|
||||
|
@ -1,76 +1,19 @@
|
||||
import asyncio
|
||||
import sys
|
||||
import traceback
|
||||
from io import StringIO
|
||||
|
||||
from pyrogram.enums import ParseMode
|
||||
|
||||
from app import Config
|
||||
from app.core import shell
|
||||
from app.core import aiohttp_tools as aio # isort:skip
|
||||
|
||||
# Run shell commands
|
||||
|
||||
async def run_cmd(bot, message):
|
||||
cmd = message.input.strip()
|
||||
status_ = await message.reply("executing...")
|
||||
proc_stdout = await shell.run_shell_cmd(cmd)
|
||||
output = f"`${cmd}`\n\n`{proc_stdout}`"
|
||||
return await status_.edit(output, name="sh.txt", disable_web_page_preview=True)
|
||||
from app import bot
|
||||
from app.social_dl import current_tasks
|
||||
|
||||
|
||||
# Shell but Live Output
|
||||
|
||||
|
||||
async def live_shell(bot, message):
|
||||
cmd = message.input.strip()
|
||||
sub_process = await shell.AsyncShell.run_cmd(cmd)
|
||||
reply = await message.reply("`getting live output....`")
|
||||
output = ""
|
||||
sleep_for = 1
|
||||
while sub_process.is_not_completed:
|
||||
# Edit message only when there's new output.
|
||||
if output != sub_process.full_std:
|
||||
output = sub_process.full_std
|
||||
if len(output) <= 4096:
|
||||
await reply.edit(f"`{output}`", disable_web_page_preview=True, parse_mode=ParseMode.MARKDOWN)
|
||||
# Reset sleep duration
|
||||
if sleep_for >= 5:
|
||||
sleep_for = 1
|
||||
# Sleep to Unblock running loop and let output reader read new
|
||||
# output.
|
||||
await asyncio.sleep(sleep_for)
|
||||
sleep_for += 1
|
||||
# If the subprocess is finished edit the message with cmd and full
|
||||
# output
|
||||
return await reply.edit(f"`$ {cmd}\n\n``{sub_process.full_std}`", name="shell.txt", disable_web_page_preview=True)
|
||||
|
||||
|
||||
# Run Python code
|
||||
async def executor_(bot, message):
|
||||
code = message.flt_input.strip()
|
||||
if not code:
|
||||
return await message.reply("exec Jo mama?")
|
||||
reply = await message.reply("executing")
|
||||
sys.stdout = codeOut = StringIO()
|
||||
sys.stderr = codeErr = StringIO()
|
||||
# Indent code as per proper python syntax
|
||||
formatted_code = "\n ".join(code.splitlines())
|
||||
try:
|
||||
# Create and initialise the function
|
||||
exec(f"async def _exec(bot, message):\n {formatted_code}")
|
||||
func_out = await locals().get("_exec")(bot, message)
|
||||
except BaseException:
|
||||
func_out = str(traceback.format_exc())
|
||||
sys.stdout = sys.__stdout__
|
||||
sys.stderr = sys.__stderr__
|
||||
output = f"`{codeOut.getvalue().strip() or codeErr.getvalue().strip() or func_out}`"
|
||||
if "-s" not in message.flags:
|
||||
output = f"> `{code}`\n\n>> {output}"
|
||||
return await reply.edit(output, name="exec.txt", disable_web_page_preview=True,parse_mode=ParseMode.MARKDOWN)
|
||||
|
||||
|
||||
if Config.DEV_MODE:
|
||||
Config.CMD_DICT["sh"] = run_cmd
|
||||
Config.CMD_DICT["shell"] = live_shell
|
||||
Config.CMD_DICT["exec"] = executor_
|
||||
@bot.add_cmd(cmd="cancel")
|
||||
async def cancel_task(bot, message):
|
||||
task_id = message.reply_id
|
||||
if not task_id:
|
||||
return await message.reply("Reply To a Command or Bot's Response Message.")
|
||||
task = current_tasks.get(task_id)
|
||||
if not task:
|
||||
return await message.reply("Task not in Currently Running Tasks.")
|
||||
reply = await message.reply("Cancelling....")
|
||||
cancelled = task.cancel()
|
||||
if cancelled:
|
||||
response = "Task Cancelled Successfully."
|
||||
else:
|
||||
response = "Task not Running.\nIt either is Finished or has Errored."
|
||||
await reply.edit(response)
|
||||
|
@ -1,39 +1,73 @@
|
||||
import asyncio
|
||||
import traceback
|
||||
|
||||
from app import Config, bot
|
||||
from app.core import filters
|
||||
from app.core.MediaHandler import ExtractAndSendMedia
|
||||
from app.core.message import Message
|
||||
|
||||
current_tasks = {}
|
||||
|
||||
|
||||
@bot.add_cmd(cmd="dl")
|
||||
async def dl(bot, message):
|
||||
reply = await bot.send_message(chat_id=message.chat.id, text="`trying to download...`")
|
||||
media = await ExtractAndSendMedia.process(message)
|
||||
reply = await bot.send_message(
|
||||
chat_id=message.chat.id, text="`trying to download...`"
|
||||
)
|
||||
task = asyncio.Task(ExtractAndSendMedia.process(message))
|
||||
current_tasks[reply.id] = task
|
||||
media = await task
|
||||
if media.exceptions:
|
||||
exceptions = "\n".join(media.exceptions)
|
||||
await bot.log(text=exceptions, func="DL", chat=message.chat.title or message.chat.first_name, name="traceback.txt")
|
||||
await bot.log(
|
||||
text=exceptions,
|
||||
func="DL",
|
||||
chat=message.chat.title or message.chat.first_name,
|
||||
name="traceback.txt",
|
||||
)
|
||||
current_tasks.pop(reply.id)
|
||||
return await reply.edit(f"Media Download Failed.")
|
||||
if media.media_objects:
|
||||
await message.delete()
|
||||
await reply.delete()
|
||||
current_tasks.pop(reply.id)
|
||||
|
||||
|
||||
@bot.on_message(filters.user_filter)
|
||||
@bot.on_edited_message(filters.user_filter)
|
||||
async def cmd_dispatcher(bot, message):
|
||||
func = Config.CMD_DICT[message.text.split(maxsplit=1)[0].lstrip(Config.TRIGGER)]
|
||||
parsed_message = Message.parse_message(message)
|
||||
func = Config.CMD_DICT[parsed_message.cmd]
|
||||
try:
|
||||
await func(bot, parsed_message)
|
||||
task = asyncio.Task(func(bot, parsed_message))
|
||||
current_tasks[message.id] = task
|
||||
await task
|
||||
except asyncio.exceptions.CancelledError:
|
||||
pass
|
||||
except BaseException:
|
||||
await bot.log(text=str(traceback.format_exc()), chat=message.chat.title or message.chat.first_name, func=func.__name__, name="traceback.txt")
|
||||
await bot.log(
|
||||
text=str(traceback.format_exc()),
|
||||
chat=message.chat.title or message.chat.first_name,
|
||||
func=func.__name__,
|
||||
name="traceback.txt",
|
||||
)
|
||||
current_tasks.pop(message.id)
|
||||
|
||||
|
||||
@bot.on_message(filters.chat_filter)
|
||||
async def dl_dispatcher(bot, message):
|
||||
func = Config.CMD_DICT["dl"]
|
||||
parsed_message = Message.parse_message(message)
|
||||
try:
|
||||
await func(bot, parsed_message)
|
||||
task = asyncio.Task(dl(bot, parsed_message))
|
||||
current_tasks[message.id] = task
|
||||
await task
|
||||
except asyncio.exceptions.CancelledError:
|
||||
pass
|
||||
except BaseException:
|
||||
await bot.log(text=str(traceback.format_exc()), chat=message.chat.title or message.chat.first_name, func=func.__name__, name="traceback.txt")
|
||||
await bot.log(
|
||||
text=str(traceback.format_exc()),
|
||||
chat=message.chat.title or message.chat.first_name,
|
||||
func=dl.__name__,
|
||||
name="traceback.txt",
|
||||
)
|
||||
current_tasks.pop(message.id)
|
||||
|
Loading…
x
Reference in New Issue
Block a user