mirror of
https://github.com/anonymousx97/social-dl.git
synced 2025-02-20 11:13:19 +08:00
v2.1.0
Add: uvLoop for non termux env. Revert: Requirements bypass. Fixes: • Gallery-DL success bug. • Stop Channel links triggering in chat. • HEIC Image format. • Optimize Filters. • Re-Load Confirmation in loader. • Remove Chat_ID check in join. • Isort removing imports. • Switch filename case before checking ext.
This commit is contained in:
parent
bc5f5f307a
commit
b7287a6685
@ -38,6 +38,11 @@
|
||||
|
||||
# Install Pypi packages
|
||||
pip install -U setuptools wheel
|
||||
|
||||
# For Termux Env:
|
||||
grep -v uvloop req.txt | xargs -n 1 pip install
|
||||
|
||||
# For Non Termux Env:
|
||||
pip install -r req.txt
|
||||
|
||||
#Setup config.env
|
||||
|
@ -5,5 +5,10 @@ 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,8 +1,6 @@
|
||||
if __name__ == "__main__":
|
||||
import tracemalloc
|
||||
tracemalloc.start()
|
||||
|
||||
from app import bot
|
||||
import app.social_dl
|
||||
|
||||
tracemalloc.start()
|
||||
bot.run(bot.boot())
|
||||
|
@ -24,4 +24,4 @@ class Gallery_DL(ScraperConfig):
|
||||
files = glob.glob(f"{self.path}/*")
|
||||
if not files:
|
||||
return self.cleanup()
|
||||
self.link = self.success = True
|
||||
self.link = self.group = self.success = True
|
||||
|
@ -1,7 +1,6 @@
|
||||
import asyncio
|
||||
import os
|
||||
import time
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import yt_dlp
|
||||
|
||||
@ -40,19 +39,18 @@ class YT_DL(ScraperConfig):
|
||||
}
|
||||
|
||||
async def download_or_extract(self):
|
||||
if "/playlist" in self.url:
|
||||
return
|
||||
if "youtu" in self.url:
|
||||
if not urlparse(self.url).query:
|
||||
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:
|
||||
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 info.get("duration", 0) >= 300:
|
||||
|
||||
if not info or info.get("duration", 0) >= 300:
|
||||
return
|
||||
|
||||
await asyncio.to_thread(yt_obj.download, self.url)
|
||||
|
@ -14,7 +14,6 @@ from app.core import aiohttp_tools, shell
|
||||
from pyrogram.errors import MediaEmpty, PhotoSaveFileInvalid, WebpageCurlFailed
|
||||
from pyrogram.types import InputMediaPhoto, InputMediaVideo
|
||||
|
||||
# Thanks Jeel Patel for the concept TG[@jeelpatel231]
|
||||
url_map = {
|
||||
"tiktok.com": Tiktok,
|
||||
"www.instagram.com": Instagram,
|
||||
@ -136,9 +135,9 @@ class ExtractAndSendMedia:
|
||||
[os.rename(file_, file_ + ".png") for file_ in glob.glob(f"{path}/*.webp")]
|
||||
images, videos, animations = [], [], []
|
||||
for file in glob.glob(f"{path}/*"):
|
||||
if file.endswith((".png", ".jpg", ".jpeg")):
|
||||
if file.lower().endswith((".png", ".jpg", ".jpeg")):
|
||||
images.append(InputMediaPhoto(file, caption=caption, has_spoiler=self.spoiler))
|
||||
if file.endswith((".mp4", ".mkv", ".webm")):
|
||||
if file.lower().endswith((".mp4", ".mkv", ".webm")):
|
||||
has_audio = await shell.check_audio(file)
|
||||
if not has_audio:
|
||||
animations.append(file)
|
||||
@ -150,11 +149,12 @@ class ExtractAndSendMedia:
|
||||
images, videos, animations = [], [], []
|
||||
downloads = await asyncio.gather(*[aiohttp_tools.in_memory_dl(url) for url in urls])
|
||||
for file_obj in downloads:
|
||||
if file_obj.name.endswith((".png", ".jpg", ".jpeg")):
|
||||
name = file_obj.name.lower()
|
||||
if name.endswith((".png", ".jpg", ".jpeg")):
|
||||
images.append(InputMediaPhoto(file_obj, caption=caption, has_spoiler=self.spoiler))
|
||||
if file_obj.name.endswith((".mp4", ".mkv", ".webm")):
|
||||
if name.endswith((".mp4", ".mkv", ".webm")):
|
||||
videos.append(InputMediaVideo(file_obj, caption=caption, has_spoiler=self.spoiler))
|
||||
if file_obj.name.endswith(".gif"):
|
||||
if name.endswith(".gif"):
|
||||
animations.append(file_obj)
|
||||
return await self.make_chunks(images, videos, animations)
|
||||
|
||||
|
@ -15,7 +15,7 @@ async def session_switch():
|
||||
await SESSION.close()
|
||||
|
||||
|
||||
async def get_json(url: str, headers: dict = None, params: dict = None, retry: bool = False, 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:
|
||||
if json_:
|
||||
@ -31,8 +31,8 @@ async def in_memory_dl(url: str):
|
||||
async with SESSION.get(url) as remote_file:
|
||||
bytes_data = await remote_file.read()
|
||||
file = BytesIO(bytes_data)
|
||||
name = os.path.basename(urlparse(url).path.rstrip("/"))
|
||||
if name.endswith(".webp"):
|
||||
name = os.path.basename(urlparse(url).path.rstrip("/")).lower()
|
||||
if name.endswith((".webp", ".heic")):
|
||||
name = name + ".jpg"
|
||||
if name.endswith(".webm"):
|
||||
name = name + ".mp4"
|
||||
|
21
app/core/client.py
Executable file → Normal file
21
app/core/client.py
Executable file → Normal file
@ -54,15 +54,19 @@ class BOT(Client):
|
||||
await aiohttp_tools.session_switch()
|
||||
|
||||
async def edit_restart_msg(self):
|
||||
if (restart_msg := os.environ.get("RESTART_MSG")) and (restart_chat := os.environ.get("RESTART_CHAT")):
|
||||
restart_msg = os.environ.get("RESTART_MSG")
|
||||
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__")
|
||||
os.environ.pop("RESTART_MSG", "")
|
||||
os.environ.pop("RESTART_CHAT", "")
|
||||
|
||||
async def import_modules(self):
|
||||
for module_ in glob.glob("app/*/*.py"):
|
||||
importlib.import_module(os.path.splitext(module_.replace("/", "."))[0])
|
||||
for py_module in glob.glob("app/**/*.py", recursive=True):
|
||||
name = os.path.splitext(py_module)[0]
|
||||
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):
|
||||
if chat or func:
|
||||
@ -75,13 +79,18 @@ class BOT(Client):
|
||||
os.execl(sys.executable, sys.executable, "-m", "app")
|
||||
|
||||
async def set_filter_list(self):
|
||||
if chats_id := Config.AUTO_DL_MESSAGE_ID:
|
||||
chats_id = Config.AUTO_DL_MESSAGE_ID
|
||||
blocked_id = Config.BLOCKED_USERS_MESSAGE_ID
|
||||
users = Config.USERS_MESSAGE_ID
|
||||
|
||||
if chats_id:
|
||||
Config.CHATS = json.loads((await super().get_messages(Config.LOG_CHAT, chats_id)).text)
|
||||
if blocked_id := Config.BLOCKED_USERS_MESSAGE_ID:
|
||||
if blocked_id:
|
||||
Config.BLOCKED_USERS = json.loads((await super().get_messages(Config.LOG_CHAT, blocked_id)).text)
|
||||
if users := Config.USERS_MESSAGE_ID:
|
||||
if users:
|
||||
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)))
|
||||
|
@ -6,14 +6,19 @@ from app import Config
|
||||
from app.core.MediaHandler import url_map
|
||||
|
||||
|
||||
def DYNAMIC_CHAT_FILTER(_, __, message):
|
||||
if not message.text or not message.text.startswith("https"):
|
||||
def Dynamic_Chat_Filter(_, __, message):
|
||||
if (
|
||||
not message.text
|
||||
or not message.text.startswith("https")
|
||||
or message.chat.id not in Config.CHATS
|
||||
or message.forward_from_chat
|
||||
):
|
||||
return False
|
||||
chat_check = message.chat.id in Config.CHATS
|
||||
user_check = True
|
||||
if user := message.from_user:
|
||||
user_check = user.id not in Config.BLOCKED_USERS and not user.is_bot
|
||||
return bool(chat_check and user_check and check_for_urls(message.text.split()))
|
||||
user = message.from_user
|
||||
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)
|
||||
|
||||
|
||||
def check_for_urls(text_list):
|
||||
@ -26,16 +31,21 @@ def check_for_urls(text_list):
|
||||
return True
|
||||
|
||||
|
||||
def DYNAMIC_CMD_FILTER(_, __, message):
|
||||
if not message.text or not message.text.startswith(Config.TRIGGER):
|
||||
def Dynamic_Cmd_Filter(_, __, message):
|
||||
if (
|
||||
not message.text
|
||||
or not message.text.startswith(Config.TRIGGER)
|
||||
or not message.from_user
|
||||
or message.from_user.id not in Config.USERS
|
||||
):
|
||||
return False
|
||||
cmd_check = message.text.split(maxsplit=1)[0].replace(Config.TRIGGER, "", 1) in Config.CMD_DICT
|
||||
user_check = False
|
||||
if user := message.from_user:
|
||||
user_check = user.id in Config.USERS
|
||||
reaction_check = bool(not message.reactions)
|
||||
return bool(cmd_check and user_check and reaction_check)
|
||||
|
||||
start_str = message.text.split(maxsplit=1)[0]
|
||||
cmd = start_str.replace(Config.TRIGGER, "", 1)
|
||||
cmd_check = cmd in Config.CMD_DICT
|
||||
reaction_check = not message.reactions
|
||||
return bool(cmd_check and reaction_check)
|
||||
|
||||
|
||||
chat_filter = _filters.create(DYNAMIC_CHAT_FILTER)
|
||||
user_filter = _filters.create(DYNAMIC_CMD_FILTER)
|
||||
chat_filter = _filters.create(Dynamic_Chat_Filter)
|
||||
user_filter = _filters.create(Dynamic_Cmd_Filter)
|
||||
|
@ -3,9 +3,10 @@ import os
|
||||
|
||||
|
||||
async def take_ss(video: str, path: str):
|
||||
await run_shell_cmd(f'''ffmpeg -hide_banner -loglevel error -ss 0.1 -i "{video}" -vframes 1 "{path}/i.png"''')
|
||||
if os.path.isfile(path + "/i.png"):
|
||||
return path + "/i.png"
|
||||
thumb = f"{path}/i.png"
|
||||
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):
|
||||
|
@ -12,11 +12,13 @@ async def loader(bot, message):
|
||||
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")
|
||||
sys.modules.pop(f"app.temp.{file_name}", None)
|
||||
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 message.reply(str(traceback.format_exc()))
|
||||
await message.reply(f"Loaded {file_name}.py.")
|
||||
return await reply.edit(str(traceback.format_exc()))
|
||||
await reply.edit(f"{status} {file_name}.py.")
|
||||
|
@ -45,8 +45,6 @@ async def get_ids(bot, message):
|
||||
@bot.add_cmd(cmd="join")
|
||||
async def join_chat(bot, message):
|
||||
chat = message.input
|
||||
if chat.isdigit():
|
||||
chat = int(f"-100{chat}")
|
||||
try:
|
||||
await bot.join_chat(chat)
|
||||
except (KeyError, BadRequest):
|
||||
|
@ -7,7 +7,7 @@ from pyrogram.enums import ParseMode
|
||||
|
||||
from app import Config
|
||||
from app.core import shell
|
||||
from app.core import aiohttp_tools as aio
|
||||
from app.core import aiohttp_tools as aio # isort:skip
|
||||
|
||||
# Run shell commands
|
||||
|
||||
|
11
req.txt
11
req.txt
@ -0,0 +1,11 @@
|
||||
aiohttp>=3.8.4
|
||||
beautifulsoup4>=4.12.2
|
||||
Brotli>=1.0.9
|
||||
gallery_dl>=1.25.7
|
||||
pyrogram>=2.0.106
|
||||
python-dotenv==0.21.0
|
||||
PyExecJS>=1.5.1
|
||||
tenacity>=8.2.2
|
||||
tgCrypto>=1.2.3
|
||||
yt-dlp>=2023.6.22
|
||||
uvloop>=0.17.0
|
16
run
16
run
@ -11,20 +11,4 @@ web.run_app(app, host='0.0.0.0', port=$API_PORT, reuse_port=True, print=None)
|
||||
|
||||
fi
|
||||
|
||||
requirements=("aiohttp>=3.8.4"
|
||||
"beautifulsoup4>=4.12.2"
|
||||
"Brotli>=1.0.9"
|
||||
"gallery_dl>=1.25.7"
|
||||
"pyrogram>=2.0.106"
|
||||
"python-dotenv==0.21.0"
|
||||
"PyExecJS>=1.5.1"
|
||||
"tenacity>=8.2.2"
|
||||
"tgCrypto>=1.2.3"
|
||||
"yt-dlp>=2023.6.22"
|
||||
)
|
||||
|
||||
for req in "${requirements[@]}"; do
|
||||
pip install "${req}";
|
||||
done
|
||||
|
||||
python3 -m app
|
Loading…
x
Reference in New Issue
Block a user