mirror of
https://github.com/anonymousx97/social-dl.git
synced 2025-02-20 11:13:19 +08:00
v2.2.1
Add: • Multiple Commands Support. • Cancel Confirmation. Fixes / Misc Changes: • Catch Message Delete Error on Bot mode. • Improve Cancelling Logic. • Switch to A Generator for AsyncShell. • Diffrenciate Traceback, Text logging. • Clean up .shell code.
This commit is contained in:
parent
216e0dcfe1
commit
1f11bc8405
@ -35,7 +35,11 @@ class BOT(Client):
|
|||||||
def the_decorator(func):
|
def the_decorator(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapper():
|
def wrapper():
|
||||||
Config.CMD_DICT[cmd] = func
|
if isinstance(cmd, list):
|
||||||
|
for _cmd in cmd:
|
||||||
|
Config.CMD_DICT[_cmd] = func
|
||||||
|
else:
|
||||||
|
Config.CMD_DICT[cmd] = func
|
||||||
|
|
||||||
wrapper()
|
wrapper()
|
||||||
return func
|
return func
|
||||||
@ -48,7 +52,7 @@ class BOT(Client):
|
|||||||
await self.set_filter_list()
|
await self.set_filter_list()
|
||||||
await aiohttp_tools.session_switch()
|
await aiohttp_tools.session_switch()
|
||||||
await self.edit_restart_msg()
|
await self.edit_restart_msg()
|
||||||
await self.log(text="#Social-dl\n__Started__")
|
await self.log(text="#SocialDL\n<i>Started</i>")
|
||||||
print("started")
|
print("started")
|
||||||
await idle()
|
await idle()
|
||||||
await aiohttp_tools.session_switch()
|
await aiohttp_tools.session_switch()
|
||||||
@ -73,15 +77,23 @@ class BOT(Client):
|
|||||||
importlib.import_module(py_name)
|
importlib.import_module(py_name)
|
||||||
|
|
||||||
async def log(
|
async def log(
|
||||||
self, text, chat=None, func=None, name="log.txt", disable_web_page_preview=True
|
self,
|
||||||
|
text="",
|
||||||
|
traceback="",
|
||||||
|
chat=None,
|
||||||
|
func=None,
|
||||||
|
name="log.txt",
|
||||||
|
disable_web_page_preview=True,
|
||||||
|
parse_mode=ParseMode.HTML,
|
||||||
):
|
):
|
||||||
if chat or func:
|
if traceback:
|
||||||
text = f"<b>Function:</b> {func}\n<b>Chat:</b> {chat}\n<b>Traceback:</b>\n{text}"
|
text = f"#Traceback\n<b>Function:</b> {func}\n<b>Chat:</b> {chat}\n<b>Traceback:</b>\n<code>{traceback}</code>"
|
||||||
return await self.send_message(
|
return await self.send_message(
|
||||||
chat_id=Config.LOG_CHAT,
|
chat_id=Config.LOG_CHAT,
|
||||||
text=text,
|
text=text,
|
||||||
name=name,
|
name=name,
|
||||||
disable_web_page_preview=disable_web_page_preview,
|
disable_web_page_preview=disable_web_page_preview,
|
||||||
|
parse_mode=parse_mode,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def restart(self):
|
async def restart(self):
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
|
|
||||||
|
from pyrogram.errors import MessageDeleteForbidden
|
||||||
from pyrogram.types import Message as MSG
|
from pyrogram.types import Message as MSG
|
||||||
|
|
||||||
from app import Config
|
from app import Config
|
||||||
@ -83,9 +84,12 @@ class Message(MSG):
|
|||||||
return reply
|
return reply
|
||||||
|
|
||||||
async def delete(self, reply=False):
|
async def delete(self, reply=False):
|
||||||
await super().delete()
|
try:
|
||||||
if reply and self.replied:
|
await super().delete()
|
||||||
await self.replied.delete()
|
if reply and self.replied:
|
||||||
|
await self.replied.delete()
|
||||||
|
except MessageDeleteForbidden:
|
||||||
|
pass
|
||||||
|
|
||||||
async def async_deleter(self, del_in, task, block):
|
async def async_deleter(self, del_in, task, block):
|
||||||
if block:
|
if block:
|
||||||
|
@ -27,34 +27,32 @@ async def run_shell_cmd(cmd):
|
|||||||
|
|
||||||
|
|
||||||
class AsyncShell:
|
class AsyncShell:
|
||||||
full_std = ""
|
|
||||||
is_not_completed = True
|
|
||||||
|
|
||||||
def __init__(self, process):
|
def __init__(self, process):
|
||||||
self.process = process
|
self.process = process
|
||||||
|
self.full_std = ""
|
||||||
|
self.is_done = False
|
||||||
|
|
||||||
async def get_output(self):
|
async def read_output(self):
|
||||||
while True:
|
while True:
|
||||||
# Check output and stop loop if it's emtpy
|
|
||||||
line = (await self.process.stdout.readline()).decode("utf-8")
|
line = (await self.process.stdout.readline()).decode("utf-8")
|
||||||
if not line:
|
if not line:
|
||||||
break
|
break
|
||||||
self.full_std += line
|
self.full_std += line
|
||||||
# Let the Subprocess complete and let it shut down
|
self.is_done = True
|
||||||
await self.process.wait()
|
await self.process.wait()
|
||||||
self.is_not_completed = False
|
|
||||||
|
async def get_output(self):
|
||||||
|
while not self.is_done:
|
||||||
|
yield self.full_std
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def run_cmd(cls, cmd):
|
async def run_cmd(cls, cmd, name="shell"):
|
||||||
# Create Subprocess and initialise self using cls
|
|
||||||
sub_process = cls(
|
sub_process = cls(
|
||||||
process=await asyncio.create_subprocess_shell(
|
process=await asyncio.create_subprocess_shell(
|
||||||
cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT
|
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.read_output())
|
||||||
asyncio.create_task(sub_process.get_output())
|
|
||||||
# Sleep for a short time to let previous task start
|
|
||||||
await asyncio.sleep(0.5)
|
await asyncio.sleep(0.5)
|
||||||
# Return Self object
|
|
||||||
return sub_process
|
return sub_process
|
||||||
|
@ -15,46 +15,52 @@ from app.core import aiohttp_tools as aio # isort:skip
|
|||||||
# Run shell commands
|
# Run shell commands
|
||||||
async def run_cmd(bot, message):
|
async def run_cmd(bot, message):
|
||||||
cmd = message.input.strip()
|
cmd = message.input.strip()
|
||||||
status_ = await message.reply("executing...")
|
reply = await message.reply("executing...")
|
||||||
proc_stdout = await shell.run_shell_cmd(cmd)
|
try:
|
||||||
|
proc_stdout = await asyncio.Task(
|
||||||
|
shell.run_shell_cmd(cmd), name=f"{message.chat.id}-{reply.id}"
|
||||||
|
)
|
||||||
|
except asyncio.exceptions.CancelledError:
|
||||||
|
return await reply.edit("`Cancelled...`")
|
||||||
output = f"`${cmd}`\n\n`{proc_stdout}`"
|
output = f"`${cmd}`\n\n`{proc_stdout}`"
|
||||||
return await status_.edit(output, name="sh.txt", disable_web_page_preview=True)
|
return await reply.edit(output, name="sh.txt", disable_web_page_preview=True)
|
||||||
|
|
||||||
|
|
||||||
# Shell but Live Output
|
# Shell but Live Output
|
||||||
async def live_shell(bot, message):
|
async def live_shell(bot, message):
|
||||||
cmd = message.input.strip()
|
try:
|
||||||
sub_process = await shell.AsyncShell.run_cmd(cmd)
|
cmd = message.input.strip()
|
||||||
reply = await message.reply("`getting live output....`")
|
reply = await message.reply("`getting live output....`")
|
||||||
output = ""
|
sub_process = await shell.AsyncShell.run_cmd(cmd)
|
||||||
sleep_for = 1
|
sleep_for = 1
|
||||||
while sub_process.is_not_completed:
|
output = ""
|
||||||
# Edit message only when there's new output.
|
async for stdout in sub_process.get_output():
|
||||||
if output != sub_process.full_std:
|
if output != stdout:
|
||||||
output = sub_process.full_std
|
if len(stdout) <= 4096:
|
||||||
if len(output) <= 4096:
|
await reply.edit(
|
||||||
await reply.edit(
|
f"`{stdout}`",
|
||||||
f"`{output}`",
|
disable_web_page_preview=True,
|
||||||
disable_web_page_preview=True,
|
parse_mode=ParseMode.MARKDOWN,
|
||||||
parse_mode=ParseMode.MARKDOWN,
|
)
|
||||||
)
|
output = stdout
|
||||||
# Reset sleep duration
|
if sleep_for >= 5:
|
||||||
if sleep_for >= 5:
|
sleep_for = 1
|
||||||
sleep_for = 1
|
await asyncio.Task(
|
||||||
# Sleep to Unblock running loop and let output reader read new
|
asyncio.sleep(sleep_for), name=f"{message.chat.id}-{reply.id}"
|
||||||
# output.
|
)
|
||||||
await asyncio.sleep(sleep_for)
|
sleep_for += 1
|
||||||
sleep_for += 1
|
return await reply.edit(
|
||||||
# If the subprocess is finished edit the message with cmd and full
|
f"`$ {cmd}\n\n``{sub_process.full_std}`",
|
||||||
# output
|
name="shell.txt",
|
||||||
return await reply.edit(
|
disable_web_page_preview=True,
|
||||||
f"`$ {cmd}\n\n``{sub_process.full_std}`",
|
)
|
||||||
name="shell.txt",
|
except asyncio.exceptions.CancelledError:
|
||||||
disable_web_page_preview=True,
|
return await reply.edit("`Cancelled...`")
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Run Python code
|
# Run Python code
|
||||||
|
|
||||||
|
|
||||||
async def executor(bot, message):
|
async def executor(bot, message):
|
||||||
code = message.flt_input.strip()
|
code = message.flt_input.strip()
|
||||||
if not code:
|
if not code:
|
||||||
@ -67,7 +73,11 @@ async def executor(bot, message):
|
|||||||
try:
|
try:
|
||||||
# Create and initialise the function
|
# Create and initialise the function
|
||||||
exec(f"async def _exec(bot, message):\n {formatted_code}")
|
exec(f"async def _exec(bot, message):\n {formatted_code}")
|
||||||
func_out = await locals()["_exec"](bot, message)
|
func_out = await asyncio.Task(
|
||||||
|
locals()["_exec"](bot, message), name=f"{message.chat.id}-{reply.id}"
|
||||||
|
)
|
||||||
|
except asyncio.exceptions.CancelledError:
|
||||||
|
return await reply.edit("`Cancelled....`")
|
||||||
except BaseException:
|
except BaseException:
|
||||||
func_out = str(traceback.format_exc())
|
func_out = str(traceback.format_exc())
|
||||||
sys.stdout = sys.__stdout__
|
sys.stdout = sys.__stdout__
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
|
import asyncio
|
||||||
|
|
||||||
from app import bot
|
from app import bot
|
||||||
from app.social_dl import current_tasks
|
|
||||||
|
|
||||||
|
|
||||||
@bot.add_cmd(cmd="cancel")
|
@bot.add_cmd(cmd=["cancel", "c"])
|
||||||
async def cancel_task(bot, message):
|
async def cancel_task(bot, message):
|
||||||
task_id = message.reply_id
|
task_id = message.reply_id
|
||||||
if not task_id:
|
if not task_id:
|
||||||
return await message.reply("Reply To a Command or Bot's Response Message.")
|
return await message.reply(
|
||||||
task = current_tasks.get(task_id)
|
"Reply To a Command or Bot's Response Message.", del_in=8
|
||||||
if not task:
|
)
|
||||||
return await message.reply("Task not in Currently Running Tasks.")
|
all_tasks = asyncio.all_tasks()
|
||||||
reply = await message.reply("Cancelling....")
|
tasks = [x for x in all_tasks if x.get_name() == f"{message.chat.id}-{task_id}"]
|
||||||
cancelled = task.cancel()
|
if not tasks:
|
||||||
if cancelled:
|
return await message.reply("Task not in Currently Running Tasks.", del_in=8)
|
||||||
response = "Task Cancelled Successfully."
|
response = ""
|
||||||
else:
|
for task in tasks:
|
||||||
response = "Task not Running.\nIt either is Finished or has Errored."
|
status = task.cancel()
|
||||||
await reply.edit(response)
|
response += f"Task: __{task.get_name()}__\nCancelled: __{status}__\n"
|
||||||
|
await message.reply(response, del_in=5)
|
||||||
|
@ -6,31 +6,27 @@ from app.core import filters
|
|||||||
from app.core.MediaHandler import ExtractAndSendMedia
|
from app.core.MediaHandler import ExtractAndSendMedia
|
||||||
from app.core.message import Message
|
from app.core.message import Message
|
||||||
|
|
||||||
current_tasks = {}
|
|
||||||
|
|
||||||
|
|
||||||
@bot.add_cmd(cmd="dl")
|
@bot.add_cmd(cmd="dl")
|
||||||
async def dl(bot, message):
|
async def dl(bot, message):
|
||||||
reply = await bot.send_message(
|
reply = await bot.send_message(
|
||||||
chat_id=message.chat.id, text="`trying to download...`"
|
chat_id=message.chat.id, text="`trying to download...`"
|
||||||
)
|
)
|
||||||
task = asyncio.Task(ExtractAndSendMedia.process(message))
|
coro = ExtractAndSendMedia.process(message)
|
||||||
current_tasks[reply.id] = task
|
task = asyncio.Task(coro, name=f"{message.chat.id}-{message.id}")
|
||||||
media = await task
|
media = await task
|
||||||
if media.exceptions:
|
if media.exceptions:
|
||||||
exceptions = "\n".join(media.exceptions)
|
exceptions = "\n".join(media.exceptions)
|
||||||
await bot.log(
|
await bot.log(
|
||||||
text=exceptions,
|
traceback=exceptions,
|
||||||
func="DL",
|
func="DL",
|
||||||
chat=message.chat.title or message.chat.first_name,
|
chat=message.chat.title or message.chat.first_name,
|
||||||
name="traceback.txt",
|
name="traceback.txt",
|
||||||
)
|
)
|
||||||
current_tasks.pop(reply.id)
|
|
||||||
return await reply.edit(f"Media Download Failed.")
|
return await reply.edit(f"Media Download Failed.")
|
||||||
if media.media_objects:
|
if media.media_objects:
|
||||||
await message.delete()
|
await message.delete()
|
||||||
await reply.delete()
|
await reply.delete()
|
||||||
current_tasks.pop(reply.id)
|
|
||||||
|
|
||||||
|
|
||||||
@bot.on_message(filters.user_filter)
|
@bot.on_message(filters.user_filter)
|
||||||
@ -38,36 +34,34 @@ async def dl(bot, message):
|
|||||||
async def cmd_dispatcher(bot, message):
|
async def cmd_dispatcher(bot, message):
|
||||||
parsed_message = Message.parse_message(message)
|
parsed_message = Message.parse_message(message)
|
||||||
func = Config.CMD_DICT[parsed_message.cmd]
|
func = Config.CMD_DICT[parsed_message.cmd]
|
||||||
|
coro = func(bot, parsed_message)
|
||||||
try:
|
try:
|
||||||
task = asyncio.Task(func(bot, parsed_message))
|
task = asyncio.Task(coro, name=f"{message.chat.id}-{message.id}")
|
||||||
current_tasks[message.id] = task
|
|
||||||
await task
|
await task
|
||||||
except asyncio.exceptions.CancelledError:
|
except asyncio.exceptions.CancelledError:
|
||||||
pass
|
await bot.log(text=f"<b>#Cancelled</b>:\n<code>{message.text}</code>")
|
||||||
except BaseException:
|
except BaseException:
|
||||||
await bot.log(
|
await bot.log(
|
||||||
text=str(traceback.format_exc()),
|
traceback=str(traceback.format_exc()),
|
||||||
chat=message.chat.title or message.chat.first_name,
|
chat=message.chat.title or message.chat.first_name,
|
||||||
func=func.__name__,
|
func=func.__name__,
|
||||||
name="traceback.txt",
|
name="traceback.txt",
|
||||||
)
|
)
|
||||||
current_tasks.pop(message.id)
|
|
||||||
|
|
||||||
|
|
||||||
@bot.on_message(filters.chat_filter)
|
@bot.on_message(filters.chat_filter)
|
||||||
async def dl_dispatcher(bot, message):
|
async def dl_dispatcher(bot, message):
|
||||||
parsed_message = Message.parse_message(message)
|
parsed_message = Message.parse_message(message)
|
||||||
|
coro = dl(bot, parsed_message)
|
||||||
try:
|
try:
|
||||||
task = asyncio.Task(dl(bot, parsed_message))
|
task = asyncio.Task(coro, name=f"{message.chat.id}-{message.id}")
|
||||||
current_tasks[message.id] = task
|
|
||||||
await task
|
await task
|
||||||
except asyncio.exceptions.CancelledError:
|
except asyncio.exceptions.CancelledError:
|
||||||
pass
|
await bot.log(text=f"<b>#Cancelled</b>:\n<code>{message.text}</code>")
|
||||||
except BaseException:
|
except BaseException:
|
||||||
await bot.log(
|
await bot.log(
|
||||||
text=str(traceback.format_exc()),
|
traceback=str(traceback.format_exc()),
|
||||||
chat=message.chat.title or message.chat.first_name,
|
chat=message.chat.title or message.chat.first_name,
|
||||||
func=dl.__name__,
|
func=dl.__name__,
|
||||||
name="traceback.txt",
|
name="traceback.txt",
|
||||||
)
|
)
|
||||||
current_tasks.pop(message.id)
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user