diff --git a/src/regular/botcommands.py b/src/regular/botcommands.py index 51f8d55..cfb6634 100644 --- a/src/regular/botcommands.py +++ b/src/regular/botcommands.py @@ -6,7 +6,7 @@ from modules.notes import set_note, notes_list, remove_note from modules.member import ( user_info, start, promote, demote, pin, - ban, unban, help_command, group_id, spoiler) + ban, unban, help_command, group_id, spoiler, runtime) from module_manager import send_module_keyboard from modules.quotes import quote_handler from modules.greetings import set_greeting, set_goodbye @@ -16,6 +16,7 @@ COMMANDS = { "/info": user_info, "/start": start, + "/runtime": runtime, "/greeting": set_greeting, "/goodbye": set_goodbye, "/wallpaper": wallpaper, @@ -52,4 +53,4 @@ async def handle_command(message, text): for cmd, func in COMMANDS.items(): if text.startswith(cmd): await func(message) - break \ No newline at end of file + break diff --git a/src/regular/main.py b/src/regular/main.py index fd1762d..4bb41c5 100644 --- a/src/regular/main.py +++ b/src/regular/main.py @@ -35,7 +35,7 @@ async def is_module_enabled_in_group(command, chat_id): 'purge', 'filter', 'filist', 'stop', 'notes', 'remove', 'add', 'help', 'goodbye', 'greeting', 'reset', 'modules', 'q', 'music', 'leave', - 'spoiler', 'blockset', 'blocklist', 'unblockset']) + 'spoiler', 'blockset', 'blocklist', 'unblockset', 'runtime']) async def cmd_handler(m): db = IMYDB('runtime/banned/groups.json') @@ -97,6 +97,8 @@ async def reply_message(m): @bot.message_handler(content_types=['sticker']) async def sticker_handler(m): + if not (await bot.get_chat_member(m.chat.id, bot.user.id)).can_delete_messages: + return await sticker_block(m) @bot.callback_query_handler(func=lambda call: call.data.startswith("help_")) diff --git a/src/regular/modules/downloader.py b/src/regular/modules/downloader.py index e27ee30..eef4f72 100644 --- a/src/regular/modules/downloader.py +++ b/src/regular/modules/downloader.py @@ -8,7 +8,7 @@ import asyncio from yt_dlp import YoutubeDL from innertube import InnerTube -from telebot.types import InputMediaPhoto +from telebot.types import InputMediaPhoto, InputMediaVideo import random import os import json @@ -84,18 +84,65 @@ def debug(msg): async def instagram_dl(m, url): try: - with YoutubeDL(ig_opts) as ydl: - info = ydl.extract_info(url, download=False) + api = f"https://delirius-apiofc.vercel.app/download/instagram?url={url}" + + async with aiohttp.ClientSession() as session: + async with session.get(api) as response: + if response.status != 200: + await bot.send_message("An error occurred") + data_json = await response.json() + + if not data_json.get("status") or not data_json.get("data"): + await bot.send_message("An error occurred") + + items = data_json.get("data", []) + + description = "" + try: + with YoutubeDL(ig_opts) as ydl: + info = ydl.extract_info(url, download=False) + description = info.get('description') or info.get('title') or "" + except Exception: + description = "" username = f"Shared by @{m.from_user.username}" if m.from_user.username else f"Shared by {user_link(m.from_user)}" - description = info.get('description', '') or info.get('title', '') - caption = f"{hcite(description, expandable=True)}\n{username}\n{hlink('Source', url, escape=False)}" + + if description: + caption = f"{hcite(description, expandable=True)}\n{username}\n{hlink('Source', url, escape=False)}" + else: + caption = f"{username}\n{hlink('Source', url, escape=False)}" if len(caption) > 1024: caption = f"{username}\n{hlink('Source', url, escape=False)}" - url = url.replace("instagram", "kkinstagram") - await bot.send_video(m.chat.id, url, caption=caption, parse_mode="HTML") + media_list = [] + for i, item in enumerate(items): + media_type = item.get("type") + media_url = item.get("url") + async with aiohttp.ClientSession() as session: + async with session.get(media_url) as response: + media_url = await response.content.read() + + current_caption = caption if i == 0 else None + + if media_type == "image": + media_list.append(InputMediaPhoto(media_url, caption=current_caption, parse_mode="HTML")) + else: + media_list.append(InputMediaVideo(media_url, caption=current_caption, parse_mode="HTML")) + + if len(media_list) == 1: + if items[0]["type"] == "image": + media_url = items[0]["url"] + async with aiohttp.ClientSession() as session: + async with session.get(media_url) as response: + media_url = await response.content.read() + await bot.send_photo(m.chat.id, media_url, caption=caption, parse_mode="HTML") + else: + await bot.send_video(m.chat.id, media_url, caption=caption, parse_mode="HTML") + else: + for i in range(0, len(media_list), 10): + await bot.send_media_group(m.chat.id, media_list[i:i+10]) + except Exception as error: await bot.send_message(m.chat.id, "An error occurred.") await log_error(bot, error, m) diff --git a/src/regular/modules/member.py b/src/regular/modules/member.py index 754dba6..5b38386 100644 --- a/src/regular/modules/member.py +++ b/src/regular/modules/member.py @@ -3,6 +3,7 @@ from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton from telebot.formatting import hspoiler import asyncio +import time from core.utils import log_error demoting_params = { @@ -56,6 +57,7 @@ - `/music`: Music search and fetching. - `/spoiler`: Resends message with spoiler added. - `/notes`: Displays a list of saved notes. + - `/runtime`: Test robot's liveness. """, "Admin": """ @@ -82,6 +84,13 @@ """ } +START_TIME = time.time() + +def format_time(seconds): mins, secs = divmod(int(seconds), 60) + hrs, mins = divmod(mins, 60) + days, hrs = divmod(hrs, 24) + return f"{days}d {hrs}h {mins}m {secs}s" + async def promote(m): try: target_user = m.reply_to_message @@ -276,6 +285,10 @@ async def help_command(m, category="General"): async def start(m): await bot.reply_to(m, "Welcome. Use /help for assistance and further understanding of the bot's functions.") +async def runtime(m): + running_time = time.time() - START_TIME + await bot.reply_to(m, f"Bot runtime:\n⏱ {format_time(running_time)}") + async def group_id(m): try: chat_id = m.chat.id @@ -348,4 +361,4 @@ async def spoiler(m): except Exception as error: await bot.send_message(m.chat.id, "An error occurred.") - await log_error(bot, error, m) \ No newline at end of file + await log_error(bot, error, m) diff --git a/src/serverless/botcommands.py b/src/serverless/botcommands.py index 03546df..43b2f9e 100644 --- a/src/serverless/botcommands.py +++ b/src/serverless/botcommands.py @@ -7,7 +7,7 @@ from modules.notes import set_note, notes_list, remove_note from modules.member import ( user_info, start, promote, demote, pin, - ban, unban, help_command, group_id, spoiler) + ban, unban, help_command, group_id, spoiler, runtime) from module_manager import send_module_keyboard from modules.quotes import quote_handler from modules.greetings import set_greeting, set_goodbye @@ -17,6 +17,7 @@ COMMANDS = { "/info": user_info, "/start": start, + "/runtime": rintime, "/greeting": set_greeting, "/goodbye": set_goodbye, "/wallpaper": wallpaper, @@ -53,4 +54,4 @@ async def handle_command(message, text): for cmd, func in COMMANDS.items(): if text.startswith(cmd): await func(message) - break \ No newline at end of file + break diff --git a/src/serverless/main.py b/src/serverless/main.py index 57921fb..fe48c6a 100644 --- a/src/serverless/main.py +++ b/src/serverless/main.py @@ -40,7 +40,7 @@ async def is_module_enabled_in_group(command, chat_id): 'purge', 'filter', 'filist', 'stop', 'notes', 'remove', 'add', 'help', 'goodbye', 'greeting', 'reset', 'modules', 'q', 'music', 'leave', - 'spoiler']) + 'spoiler', 'runtime']) async def cmd_handler(m): db = IMYDB('runtime/banned/groups.json') @@ -102,6 +102,8 @@ async def reply_message(m): @bot.message_handler(content_types=['sticker']) async def sticker_handler(m): + if not (await bot.get_chat_member(m.chat.id, bot.user.id)).can_delete_messages: + return await sticker_block(m) @bot.callback_query_handler(func=lambda call: call.data.startswith("help_")) diff --git a/src/serverless/modules/downloader.py b/src/serverless/modules/downloader.py index 3542fcd..8040e8e 100644 --- a/src/serverless/modules/downloader.py +++ b/src/serverless/modules/downloader.py @@ -7,7 +7,7 @@ import asyncio from innertube import InnerTube from yt_dlp import YoutubeDL -from telebot.types import InputMediaPhoto +from telebot.types import InputMediaPhoto, InputMediaVideo import random async def wait_until_ok(url, delay=1): @@ -63,26 +63,80 @@ async def extract_supported_url(m): elif url.startswith("https://x.com") or url.startswith("https://www.x.com"): await twitter_dl(m, url) +class loggerOutputs: + def error(msg): + pass + def warning(msg): + pass + def debug(msg): + pass ig_opts = { "quiet": True, - "no_warnings": True, + "logger": loggerOutputs } async def instagram_dl(m, url): try: - with YoutubeDL(ig_opts) as ydl: - info = ydl.extract_info(url, download=False) + api = f"https://delirius-apiofc.vercel.app/download/instagram?url={url}" + + async with aiohttp.ClientSession() as session: + async with session.get(api) as response: + if response.status != 200: + await bot.send_message("An error occurred") + data_json = await response.json() + + if not data_json.get("status") or not data_json.get("data"): + await bot.send_message("An error occurred") + + items = data_json.get("data", []) + + description = "" + try: + with YoutubeDL(ig_opts) as ydl: + info = ydl.extract_info(url, download=False) + description = info.get('description') or info.get('title') or "" + except Exception: + description = "" username = f"Shared by @{m.from_user.username}" if m.from_user.username else f"Shared by {user_link(m.from_user)}" - description = info.get('description', '') or info.get('title', '') - caption = f"{hcite(description, expandable=True)}\n{username}\n{hlink('Source', url, escape=False)}" + + if description: + caption = f"{hcite(description, expandable=True)}\n{username}\n{hlink('Source', url, escape=False)}" + else: + caption = f"{username}\n{hlink('Source', url, escape=False)}" if len(caption) > 1024: caption = f"{username}\n{hlink('Source', url, escape=False)}" - url = url.replace("instagram", "kkinstagram") - await bot.send_video(m.chat.id, url, caption=caption, parse_mode="HTML") + media_list = [] + for i, item in enumerate(items): + media_type = item.get("type") + media_url = item.get("url") + async with aiohttp.ClientSession() as session: + async with session.get(media_url) as response: + media_url = await response.content.read() + + current_caption = caption if i == 0 else None + + if media_type == "image": + media_list.append(InputMediaPhoto(media_url, caption=current_caption, parse_mode="HTML")) + else: + media_list.append(InputMediaVideo(media_url, caption=current_caption, parse_mode="HTML")) + + if len(media_list) == 1: + if items[0]["type"] == "image": + media_url = items[0]["url"] + async with aiohttp.ClientSession() as session: + async with session.get(media_url) as response: + media_url = await response.content.read() + await bot.send_photo(m.chat.id, media_url, caption=caption, parse_mode="HTML") + else: + await bot.send_video(m.chat.id, media_url, caption=caption, parse_mode="HTML") + else: + for i in range(0, len(media_list), 10): + await bot.send_media_group(m.chat.id, media_list[i:i+10]) + except Exception as error: await bot.send_message(m.chat.id, "An error occurred.") await log_error(bot, error, m) diff --git a/src/serverless/modules/member.py b/src/serverless/modules/member.py index 754dba6..df5f179 100644 --- a/src/serverless/modules/member.py +++ b/src/serverless/modules/member.py @@ -3,6 +3,7 @@ from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton from telebot.formatting import hspoiler import asyncio +import time from core.utils import log_error demoting_params = { @@ -56,6 +57,7 @@ - `/music`: Music search and fetching. - `/spoiler`: Resends message with spoiler added. - `/notes`: Displays a list of saved notes. + - `/runtime`: Test robot's liveness. """, "Admin": """ @@ -82,6 +84,13 @@ """ } +START_TIME = time.time() + +def format_time(seconds): + mins, secs = divmod(int(seconds), 60) + hrs, mins = divmod(mins, 60) + days, hrs = divmod(hrs, 24) return f"{days}d {hrs}h {mins}m {secs}s" + async def promote(m): try: target_user = m.reply_to_message @@ -276,6 +285,9 @@ async def help_command(m, category="General"): async def start(m): await bot.reply_to(m, "Welcome. Use /help for assistance and further understanding of the bot's functions.") +async def runtime(m): + running_time = time.time() - START_TIME await bot.reply_to(m, f"Bot runtime:\n⏱ {format_time(running_time)}") + async def group_id(m): try: chat_id = m.chat.id @@ -348,4 +360,4 @@ async def spoiler(m): except Exception as error: await bot.send_message(m.chat.id, "An error occurred.") - await log_error(bot, error, m) \ No newline at end of file + await log_error(bot, error, m)