diff --git a/README.md b/README.md index 6e6bc7c6..df393347 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ If you want help me fixing some error in my bot, you can make pull request to th | Basic Admin Feature |✔️| | AFK Feature |✔️| | Downloader FB, TikTok and YT-DLP Support |✔️| -| MultiLanguage Support (Still Beta) |⚠️| +| MultiLanguage Support (Unfinished) |⚠️| | NightMode |✔️| | ChatBot based on OpenAI |✔️| | MissKaty Mata |✔️| diff --git a/assets/IronFont.otf b/assets/IronFont.otf new file mode 100644 index 00000000..563fb0ea Binary files /dev/null and b/assets/IronFont.otf differ diff --git a/assets/statsbg.jpg b/assets/statsbg.jpg new file mode 100644 index 00000000..eff8e935 Binary files /dev/null and b/assets/statsbg.jpg differ diff --git a/misskaty/plugins/admin.py b/misskaty/plugins/admin.py index 37b7af6c..9ad1f8e5 100644 --- a/misskaty/plugins/admin.py +++ b/misskaty/plugins/admin.py @@ -1,5 +1,29 @@ +""" +MIT License + +Copyright (c) 2023 TheHamkerCat + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" import asyncio import re +import os from logging import getLogger from time import time @@ -56,6 +80,9 @@ __HELP__ = """ /unmute - Unmute A User /ban_ghosts - Ban Deleted Accounts /report | @admins | @admin - Report A Message To Admins. +/set_chat_title - Change The Name Of A Group/Channel. +/set_chat_photo - Change The PFP Of A Group/Channel. +/set_user_title - Change The Administrator Title Of An Admin. """ @@ -704,3 +731,63 @@ async def report_user(self: Client, ctx: Message, strings) -> "Message": continue text += f" 5000000: + return await ctx.reply("File size too large.") + + photo = await reply.download() + await ctx.chat.set_photo(photo) + await ctx.reply_text("Successfully Changed Group Photo") + os.remove(photo) \ No newline at end of file diff --git a/misskaty/plugins/dev.py b/misskaty/plugins/dev.py index 1845e0ca..16f76029 100644 --- a/misskaty/plugins/dev.py +++ b/misskaty/plugins/dev.py @@ -16,14 +16,15 @@ from database.users_chats_db import db from inspect import getfullargspec from typing import Any, Optional, Tuple -from psutil import cpu_percent +from psutil import cpu_percent, Process from psutil import disk_usage as disk_usage_percent -from psutil import virtual_memory +from psutil import virtual_memory, cpu_count, boot_time, net_io_counters from pyrogram import enums, filters, Client, __version__ as pyrover -from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message +from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message, InputMediaPhoto from pyrogram.raw.types import UpdateBotStopped from pykeyboard import InlineKeyboard, InlineButton +from PIL import Image, ImageDraw, ImageFont from misskaty import app, user, botStartTime, misskaty_version, BOT_NAME from misskaty.helper.http import http @@ -116,32 +117,86 @@ async def server_stats(self: Client, ctx: Message) -> "Message": """ Give system stats of the server. """ - try: - serverinfo = await http.get("https://ipinfo.io/json") - org = serverinfo.json()["org"] - except: - org = "N/A" - currentTime = get_readable_time(time() - botStartTime) - total, used, free = disk_usage(".") - total = get_readable_file_size(total) - used = get_readable_file_size(used) - free = get_readable_file_size(free) - neofetch = (await shell_exec("neofetch --stdout"))[0] - caption = f""" -{BOT_NAME} {misskaty_version} is Up and Running successfully. -Bot Uptime: {currentTime} -Pyrogram Version: {pyrover} -Python Version: {sys.version_info[0]}.{sys.version_info[1]}.{sys.version_info[2]} {sys.version_info[3].title()} -Server: {org} -Total Disk Space: {total} -Used: {used}({disk_usage_percent("/").percent}%) -Free: {free} -CPU Usage: {cpu_percent()}% -RAM Usage: {virtual_memory().percent}% + image = Image.open("assets/statsbg.jpg").convert("RGB") + IronFont = ImageFont.truetype("assets/IronFont.otf", 42) + draw = ImageDraw.Draw(image) -{neofetch} -""" - await ctx.reply_msg(caption) + def draw_progressbar(coordinate, progress): + progress = 110 + (progress * 10.8) + draw.ellipse((105, coordinate - 25, 127, coordinate), fill="#FFFFFF") + draw.rectangle((120, coordinate, progress, coordinate - 25), fill="#FFFFFF") + draw.ellipse( + (progress - 7, coordinate - 25, progress + 15, coordinate), fill="#FFFFFF" + ) + + total, used, free = disk_usage_percent(".") + process = Process(os.getpid()) + + botuptime = get_readable_time(time() - BotStartTime) + osuptime = get_readable_time(time() - boot_time()) + currentTime = get_readable_time(time() - botStartTime) + botusage = f"{round(process.memory_info()[0]/1024 ** 2)} MB" + + upload = get_readable_file_size(net_io_counters().bytes_sent) + download = get_readable_file_size(net_io_counters().bytes_recv) + + cpu_percentage = cpu_percent() + cpu_count = cpu_count() + + ram_percentage = virtual_memory().percent + ram_total = get_readable_file_size(virtual_memory().total) + ram_used = get_readable_file_size(virtual_memory().used) + + disk_percenatge = disk_usage("/").percent + disk_total = get_readable_file_size(total) + disk_used = get_readable_file_size(used) + disk_free = get_readable_file_size(free) + + caption = f"{BOT_NAME} {misskaty_version} is Up and Running successfully.**OS Uptime:** {osuptime}\nBot Uptime: {currentTime}\n**Bot Usage:** {botusage}\n\n**Total Space:** {disk_total}\n**Free Space:** {disk_free}\n\n**Download:** {download}\n**Upload:** {upload}\n\nPyrogram Version: {pyrover}\nPython Version: {sys.version_info[0]}.{sys.version_info[1]}.{sys.version_info[2]} {sys.version_info[3].title()}" + + start = datetime.now() + msg = await message.reply_photo( + photo="https://te.legra.ph/file/30a82c22854971d0232c7.jpg", + caption=caption, + quote=True, + ) + end = datetime.now() + + draw_progressbar(243, int(cpu_percentage)) + draw.text( + (225, 153), + f"( {cpu_count} core, {cpu_percentage}% )", + (255, 255, 255), + font=IronFont, + ) + + draw_progressbar(395, int(disk_percenatge)) + draw.text( + (335, 302), + f"( {disk_used} / {disk_total}, {disk_percenatge}% )", + (255, 255, 255), + font=IronFont, + ) + + draw_progressbar(533, int(ram_percentage)) + draw.text( + (225, 445), + f"( {ram_used} / {ram_total} , {ram_percentage}% )", + (255, 255, 255), + font=IronFont, + ) + + draw.text((335, 600), f"{botuptime}", (255, 255, 255), font=IronFont) + draw.text( + (857, 607), + f"{(end-start).microseconds/1000} ms", + (255, 255, 255), + font=IronFont, + ) + + image.save("stats.png") + await msg.edit_media(media=InputMediaPhoto("stats.png", caption=caption)) + os.remove("stats.png") @app.on_message(filters.command(["shell", "sh", "term"], COMMAND_HANDLER) & filters.user(SUDO)) diff --git a/misskaty/plugins/ytdl_plugins.py b/misskaty/plugins/ytdl_plugins.py index 21af1583..47b3ebb9 100644 --- a/misskaty/plugins/ytdl_plugins.py +++ b/misskaty/plugins/ytdl_plugins.py @@ -17,7 +17,7 @@ from misskaty.helper.localization import use_chat_lang from misskaty.vars import COMMAND_HANDLER, LOG_CHANNEL, FF_MPEG_NAME LOGGER = getLogger(__name__) -regex = recompile(r"(https?://)?(www\.)?(youtube|youtu|youtube-nocookie)\.(com|be)/(watch\?v=|embed/|v/|.+\?v=)?(?P[A-Za-z0-9\-=_]{11})") +regex = "^(https?://)?(www\.)?(youtube|youtu|youtube-nocookie)\.(com|be)/(watch\?v=|embed/|v/|.+\?v=)?(?P[A-Za-z0-9\-=_]{11})" YT_DB = {} @@ -34,7 +34,7 @@ async def ytsearch(self: Client, ctx: Message, strings): return await ctx.reply_msg(strings("no_channel")) if len(ctx.command) == 1: return await ctx.reply_msg(strings("no_query")) - query = ctx.text.split(" ", maxsplit=1)[1] + query = ctx.text.split(" ", maxsplit=1)[1] if len(ctx.command) > 1 search_key = rand_key() YT_DB[search_key] = query search = await main.VideosSearch(query).next() @@ -60,7 +60,7 @@ async def ytsearch(self: Client, ctx: Message, strings): await ctx.reply_photo(img, caption=caption, reply_markup=markup, quote=True) -@app.on_message(filters.command(["ytdown"], COMMAND_HANDLER)) +@app.on_message(filters.command(["ytdown"], COMMAND_HANDLER) | filters.regex(YT_REGEX) & ~filters.channel) @capture_err @ratelimiter @use_chat_lang() @@ -69,7 +69,7 @@ async def ytdownv2(self: Client, ctx: Message, strings): return await ctx.reply_msg(strings("no_channel")) if len(ctx.command) == 1: return await ctx.reply_msg(strings("invalid_link")) - url = ctx.input + url = ctx.input if len(ctx.command) > 1 else ctx.text async with iYTDL(log_group_id=0, cache_path="cache", ffmpeg_location=f"/usr/bin/{FF_MPEG_NAME}") as ytdl: try: x = await ytdl.parse(url, extract=True) @@ -166,7 +166,6 @@ async def ytdl_gendl_callback(self: Client, cq: CallbackQuery, strings): key=key[0], downtype=media_type, update=cq, - caption_link=video_link, ) except DownloadFailedError as e: await cq.edit_message_caption(f"Download Failed - {e}")