diff --git a/plugins/__init__.py b/plugins/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..45d1e4d76d93978bf394c0da906e3c286ea1bfe9
--- /dev/null
+++ b/plugins/__init__.py
@@ -0,0 +1,102 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+import asyncio
+import os
+import time
+from random import choice
+
+import requests
+from telethon import Button, events
+from telethon.tl import functions, types # pylint:ignore
+from telethon.tl.custom.message import CustomMarkdown
+
+from pyUltroid import *
+from pyUltroid._misc._assistant import asst_cmd, callback, in_pattern
+from pyUltroid._misc._decorators import ultroid_cmd
+from pyUltroid._misc._wrappers import eod, eor
+from pyUltroid.dB import DEVLIST, ULTROID_IMAGES
+from pyUltroid.fns.helper import *
+from pyUltroid.fns.misc import *
+from pyUltroid.fns.tools import *
+from pyUltroid.startup._database import _BaseDatabase as Database
+from pyUltroid.version import __version__, ultroid_version
+from strings import get_help, get_string
+
+udB: Database
+
+Redis = udB.get_key
+con = TgConverter
+quotly = Quotly()
+OWNER_NAME = ultroid_bot.full_name
+OWNER_ID = ultroid_bot.uid
+
+ultroid_bot: UltroidClient
+asst: UltroidClient
+
+LOG_CHANNEL = udB.get_key("LOG_CHANNEL")
+
+ultroid_bot.parse_mode = CustomMarkdown()
+
+def inline_pic():
+ INLINE_PIC = udB.get_key("INLINE_PIC")
+ if INLINE_PIC is None:
+ INLINE_PIC = choice(ULTROID_IMAGES)
+ elif INLINE_PIC == False:
+ INLINE_PIC = None
+ return INLINE_PIC
+
+
+Telegraph = telegraph_client()
+
+List = []
+Dict = {}
+InlinePlugin = {}
+N = 0
+cmd = ultroid_cmd
+STUFF = {}
+
+# Chats, which needs to be ignore for some cases
+# Considerably, there can be many
+# Feel Free to Add Any other...
+
+NOSPAM_CHAT = [
+ -1001361294038, # UltroidSupportChat
+ -1001387666944, # PyrogramChat
+ -1001109500936, # TelethonChat
+ -1001050982793, # Python
+ -1001256902287, # DurovsChat
+ -1001473548283, # SharingUserbot
+]
+
+KANGING_STR = [
+ "Using Witchery to kang this sticker...",
+ "Plagiarising hehe...",
+ "Inviting this sticker over to my pack...",
+ "Kanging this sticker...",
+ "Hey that's a nice sticker!\nMind if I kang?!..",
+ "Hehe me stel ur stiker...",
+ "Ay look over there (☉。☉)!→\nWhile I kang this...",
+ "Roses are red violets are blue, kanging this sticker so my pack looks cool",
+ "Imprisoning this sticker...",
+ "Mr.Steal-Your-Sticker is stealing this sticker... ",
+]
+
+ATRA_COL = [
+ "DarkCyan",
+ "DeepSkyBlue",
+ "DarkTurquoise",
+ "Cyan",
+ "LightSkyBlue",
+ "Turquoise",
+ "MediumVioletRed",
+ "Aquamarine",
+ "Lightcyan",
+ "Azure",
+ "Moccasin",
+ "PowderBlue",
+]
diff --git a/plugins/_chatactions.py b/plugins/_chatactions.py
new file mode 100644
index 0000000000000000000000000000000000000000..be6379a6c2c673b4134f842a8935321ef95c5a9d
--- /dev/null
+++ b/plugins/_chatactions.py
@@ -0,0 +1,350 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+import asyncio
+
+from telethon import events
+from telethon.errors.rpcerrorlist import UserNotParticipantError
+from telethon.tl.functions.channels import GetParticipantRequest
+from telethon.utils import get_display_name
+
+from pyUltroid.dB import stickers
+from pyUltroid.dB.echo_db import check_echo
+from pyUltroid.dB.forcesub_db import get_forcesetting
+from pyUltroid.dB.gban_mute_db import is_gbanned
+from pyUltroid.dB.greetings_db import get_goodbye, get_welcome, must_thank
+from pyUltroid.dB.nsfw_db import is_profan
+from pyUltroid.fns.helper import check_reply_to, inline_mention
+from pyUltroid.fns.tools import (
+ async_searcher,
+ create_tl_btn,
+ get_chatbot_reply,
+ get_oracle_reply,
+)
+
+try:
+ from ProfanityDetector import detector
+except ImportError:
+ detector = None
+from . import LOG_CHANNEL, LOGS, asst, get_string, types, udB, ultroid_bot
+from ._inline import something
+
+if not udB.get_key("ORACLE_USERS"):
+ udB.set_key("ORACLE_USERS", {})
+if not udB.get_key("CHATBOT_USERS"):
+ udB.set_key("CHATBOT_USERS", {})
+
+@ultroid_bot.on(events.ChatAction())
+async def Function(event):
+ try:
+ await DummyHandler(event)
+ except Exception as er:
+ LOGS.exception(er)
+
+
+async def DummyHandler(ult):
+ # clean chat actions
+ key = udB.get_key("CLEANCHAT") or []
+ if ult.chat_id in key:
+ try:
+ await ult.delete()
+ except BaseException:
+ pass
+
+ # thank members
+ if must_thank(ult.chat_id):
+ chat_count = (await ult.client.get_participants(ult.chat_id, limit=0)).total
+ if chat_count % 100 == 0:
+ stik_id = chat_count / 100 - 1
+ sticker = stickers[stik_id]
+ await ult.respond(file=sticker)
+ # force subscribe
+ if (
+ udB.get_key("FORCESUB")
+ and ((ult.user_joined or ult.user_added))
+ and get_forcesetting(ult.chat_id)
+ ):
+ user = await ult.get_user()
+ if not user.bot:
+ joinchat = get_forcesetting(ult.chat_id)
+ try:
+ await ultroid_bot(GetParticipantRequest(int(joinchat), user.id))
+ except UserNotParticipantError:
+ await ultroid_bot.edit_permissions(
+ ult.chat_id, user.id, send_messages=False
+ )
+ res = await ultroid_bot.inline_query(
+ asst.me.username, f"fsub {user.id}_{joinchat}"
+ )
+ await res[0].click(ult.chat_id, reply_to=ult.action_message.id)
+
+ if ult.user_joined or ult.added_by:
+ user = await ult.get_user()
+ chat = await ult.get_chat()
+ # gbans and @UltroidBans checks
+ if udB.get_key("ULTROID_BANS"):
+ try:
+ is_banned = await async_searcher(
+ "https://bans.ultroid.tech/api/status",
+ json={"userId": user.id},
+ post=True,
+ re_json=True,
+ )
+ if is_banned["is_banned"]:
+ await ult.client.edit_permissions(
+ chat.id,
+ user.id,
+ view_messages=False,
+ )
+ await ult.respond(
+ f'**@UltroidBans:** Banned user detected and banned!\n`{str(is_banned)}`.\nBan reason: {is_banned["reason"]}',
+ )
+
+ except BaseException:
+ pass
+ reason = is_gbanned(user.id)
+ if reason and chat.admin_rights:
+ try:
+ await ult.client.edit_permissions(
+ chat.id,
+ user.id,
+ view_messages=False,
+ )
+ gban_watch = get_string("can_1").format(inline_mention(user), reason)
+ await ult.reply(gban_watch)
+ except Exception as er:
+ LOGS.exception(er)
+
+ # greetings
+ elif get_welcome(ult.chat_id):
+ user = await ult.get_user()
+ chat = await ult.get_chat()
+ title = chat.title or "this chat"
+ count = (
+ chat.participants_count
+ or (await ult.client.get_participants(chat, limit=0)).total
+ )
+ mention = inline_mention(user)
+ name = user.first_name
+ fullname = get_display_name(user)
+ uu = user.username
+ username = f"@{uu}" if uu else mention
+ wel = get_welcome(ult.chat_id)
+ msgg = wel["welcome"]
+ med = wel["media"] or None
+ userid = user.id
+ msg = None
+ if msgg:
+ msg = msgg.format(
+ mention=mention,
+ group=title,
+ count=count,
+ name=name,
+ fullname=fullname,
+ username=username,
+ userid=userid,
+ )
+ if wel.get("button"):
+ btn = create_tl_btn(wel["button"])
+ await something(ult, msg, med, btn)
+ elif msg:
+ send = await ult.reply(
+ msg,
+ file=med,
+ )
+ await asyncio.sleep(150)
+ await send.delete()
+ else:
+ await ult.reply(file=med)
+ elif (ult.user_left or ult.user_kicked) and get_goodbye(ult.chat_id):
+ user = await ult.get_user()
+ chat = await ult.get_chat()
+ title = chat.title or "this chat"
+ count = (
+ chat.participants_count
+ or (await ult.client.get_participants(chat, limit=0)).total
+ )
+ mention = inline_mention(user)
+ name = user.first_name
+ fullname = get_display_name(user)
+ uu = user.username
+ username = f"@{uu}" if uu else mention
+ wel = get_goodbye(ult.chat_id)
+ msgg = wel["goodbye"]
+ med = wel["media"]
+ userid = user.id
+ msg = None
+ if msgg:
+ msg = msgg.format(
+ mention=mention,
+ group=title,
+ count=count,
+ name=name,
+ fullname=fullname,
+ username=username,
+ userid=userid,
+ )
+ if wel.get("button"):
+ btn = create_tl_btn(wel["button"])
+ await something(ult, msg, med, btn)
+ elif msg:
+ send = await ult.reply(
+ msg,
+ file=med,
+ )
+ await asyncio.sleep(150)
+ await send.delete()
+ else:
+ await ult.reply(file=med)
+
+
+@ultroid_bot.on(events.NewMessage(incoming=True))
+async def chatBot_replies(e):
+ if e.sender_id in udB.get_key("CHATBOT_USERS"):
+ xxrep = await check_reply_to(e)
+ else:
+ return
+
+ if xxrep:
+ sender = await e.get_sender()
+ if not isinstance(sender, types.User) or sender.bot:
+ return
+ if check_echo(e.chat_id, e.sender_id):
+ try:
+ await e.respond(e.message)
+ except Exception as er:
+ LOGS.exception(er)
+ key = udB.get_key("CHATBOT_USERS") or {}
+ if e.text and key.get(e.chat_id) and sender.id in key[e.chat_id]:
+ # Simulate typing indicator
+ async with e.client.action(e.chat_id, "typing"):
+ msg = await get_chatbot_reply(e.message.message)
+ if msg:
+ sleep = udB.get_key("CHATBOT_SLEEP") or 1.5
+ await asyncio.sleep(sleep)
+
+ # Check if the message length exceeds a certain threshold
+ if len(msg) > 4096:
+ # Create a temporary text file
+ with tempfile.NamedTemporaryFile(
+ mode="w+", delete=False
+ ) as temp_file:
+ temp_file.write(msg)
+
+ # Send the text file with a caption
+ await e.client.send_file(
+ e.chat_id,
+ temp_file.name,
+ caption="Here is the response in a text file.",
+ )
+
+ # Delete the temporary text file
+ os.remove(temp_file.name)
+ else:
+ # Send the message directly
+ await e.reply(msg)
+
+ chat = await e.get_chat()
+ if e.is_group and sender.username:
+ await uname_stuff(e.sender_id, sender.username, sender.first_name)
+ elif e.is_private and chat.username:
+ await uname_stuff(e.sender_id, chat.username, chat.first_name)
+ if detector and is_profan(e.chat_id) and e.text:
+ x, y = detector(e.text)
+ if y:
+ await e.delete()
+
+
+@ultroid_bot.on(events.NewMessage(incoming=True))
+async def oracleBot_replies(e):
+ if e.sender_id in udB.get_key("ORACLE_USERS"):
+ xxxrep = await check_reply_to(e)
+ else:
+ return
+
+ if xxxrep:
+ sender = await e.get_sender()
+ if not isinstance(sender, types.User) or sender.bot:
+ return
+ if check_echo(e.chat_id, e.sender_id):
+ try:
+ await e.respond(e.message)
+ except Exception as er:
+ LOGS.exception(er)
+ key = udB.get_key("ORACLE_USERS") or {}
+ if e.text and key.get(e.chat_id) and sender.id in key[e.chat_id]:
+ # Simulate typing indicator
+ async with e.client.action(e.chat_id, "typing"):
+ msg = await get_oracle_reply(
+ e.message.message, user_id=sender.id, mongo_url=MONGO_URI
+ )
+ if msg:
+ sleep = udB.get_key("ORACLE_SLEEP") or 1.5
+ await asyncio.sleep(sleep)
+
+ # Check if the message length exceeds a certain threshold
+ if len(msg) > 4096:
+ # Create a temporary text file
+ with tempfile.NamedTemporaryFile(
+ mode="w+", delete=False
+ ) as temp_file:
+ temp_file.write(msg)
+
+ # Send the text file with a caption
+ await e.client.send_file(
+ e.chat_id,
+ temp_file.name,
+ caption="Here is the response in a text file",
+ )
+
+ # Delete the temporary text file
+ os.remove(temp_file.name)
+ else:
+ # Send the message directly
+ await e.reply(msg)
+
+ chat = await e.get_chat()
+ if e.is_group and sender.username:
+ await uname_stuff(e.sender_id, sender.username, sender.first_name)
+ elif e.is_private and chat.username:
+ await uname_stuff(e.sender_id, chat.username, chat.first_name)
+ if detector and is_profan(e.chat_id) and e.text:
+ x, y = detector(e.text)
+ if y:
+ await e.delete()
+
+
+@ultroid_bot.on(events.Raw(types.UpdateUserName))
+async def uname_change(e):
+ await uname_stuff(e.user_id, e.usernames[0] if e.usernames else None, e.first_name)
+
+
+async def uname_stuff(id, uname, name):
+ if udB.get_key("USERNAME_LOG"):
+ old_ = udB.get_key("USERNAME_DB") or {}
+ old = old_.get(id)
+ # Ignore Name Logs
+ if old and old == uname:
+ return
+ if old and uname:
+ await asst.send_message(
+ LOG_CHANNEL,
+ get_string("can_2").format(old, uname),
+ )
+ elif old:
+ await asst.send_message(
+ LOG_CHANNEL,
+ get_string("can_3").format(f"[{name}](tg://user?id={id})", old),
+ )
+ elif uname:
+ await asst.send_message(
+ LOG_CHANNEL,
+ get_string("can_4").format(f"[{name}](tg://user?id={id})", uname),
+ )
+
+ old_[id] = uname
+ udB.set_key("USERNAME_DB", old_)
diff --git a/plugins/_help.py b/plugins/_help.py
new file mode 100644
index 0000000000000000000000000000000000000000..b36101e7f5d5769f2c309797905e265bdc7e8f1a
--- /dev/null
+++ b/plugins/_help.py
@@ -0,0 +1,136 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from telethon.errors.rpcerrorlist import (
+ BotInlineDisabledError,
+ BotMethodInvalidError,
+ BotResponseTimeoutError,
+)
+from telethon.tl.custom import Button
+
+from pyUltroid.dB._core import HELP, LIST
+from pyUltroid.fns.tools import cmd_regex_replace
+
+from . import HNDLR, LOGS, OWNER_NAME, asst, get_string, inline_pic, udB, ultroid_cmd
+
+_main_help_menu = [
+ [
+ Button.inline(get_string("help_4"), data="uh_Official_"),
+ Button.inline(get_string("help_5"), data="uh_Addons_"),
+ ],
+ [
+ Button.inline(get_string("help_6"), data="uh_VCBot_"),
+ Button.inline(get_string("help_7"), data="inlone"),
+ ],
+ [
+ Button.inline(get_string("help_8"), data="ownr"),
+ Button.url(
+ get_string("help_9"), url=f"https://t.me/{asst.me.username}?start=set"
+ ),
+ ],
+ [Button.inline(get_string("help_10"), data="close")],
+]
+
+
+@ultroid_cmd(pattern="help( (.*)|$)")
+async def _help(ult):
+ plug = ult.pattern_match.group(1).strip()
+ chat = await ult.get_chat()
+ if plug:
+ try:
+ if plug in HELP["Official"]:
+ output = f"**Plugin** - `{plug}`\n"
+ for i in HELP["Official"][plug]:
+ output += i
+ output += "\n© @TeamUltroid"
+ await ult.eor(output)
+ elif HELP.get("Addons") and plug in HELP["Addons"]:
+ output = f"**Plugin** - `{plug}`\n"
+ for i in HELP["Addons"][plug]:
+ output += i
+ output += "\n© @TeamUltroid"
+ await ult.eor(output)
+ elif HELP.get("VCBot") and plug in HELP["VCBot"]:
+ output = f"**Plugin** - `{plug}`\n"
+ for i in HELP["VCBot"][plug]:
+ output += i
+ output += "\n© @TeamUltroid"
+ await ult.eor(output)
+ else:
+ try:
+ x = get_string("help_11").format(plug)
+ for d in LIST[plug]:
+ x += HNDLR + d
+ x += "\n"
+ x += "\n© @TeamUltroid"
+ await ult.eor(x)
+ except BaseException:
+ file = None
+ compare_strings = []
+ for file_name in LIST:
+ compare_strings.append(file_name)
+ value = LIST[file_name]
+ for j in value:
+ j = cmd_regex_replace(j)
+ compare_strings.append(j)
+ if j.strip() == plug:
+ file = file_name
+ break
+ if not file:
+ # the enter command/plugin name is not found
+ text = f"`{plug}` is not a valid plugin!"
+ best_match = None
+ for _ in compare_strings:
+ if plug in _ and not _.startswith("_"):
+ best_match = _
+ break
+ if best_match:
+ text += f"\nDid you mean `{best_match}`?"
+ return await ult.eor(text)
+ output = f"**Command** `{plug}` **found in plugin** - `{file}`\n"
+ if file in HELP["Official"]:
+ for i in HELP["Official"][file]:
+ output += i
+ elif HELP.get("Addons") and file in HELP["Addons"]:
+ for i in HELP["Addons"][file]:
+ output += i
+ elif HELP.get("VCBot") and file in HELP["VCBot"]:
+ for i in HELP["VCBot"][file]:
+ output += i
+ output += "\n© @TeamUltroid"
+ await ult.eor(output)
+ except BaseException as er:
+ LOGS.exception(er)
+ await ult.eor("Error 🤔 occured.")
+ else:
+ try:
+ results = await ult.client.inline_query(asst.me.username, "ultd")
+ except BotMethodInvalidError:
+ z = []
+ for x in LIST.values():
+ z.extend(x)
+ cmd = len(z) + 10
+ if udB.get_key("MANAGER") and udB.get_key("DUAL_HNDLR") == "/":
+ _main_help_menu[2:3] = [[Button.inline("• Manager Help •", "mngbtn")]]
+ return await ult.reply(
+ get_string("inline_4").format(
+ OWNER_NAME,
+ len(HELP["Official"]),
+ len(HELP["Addons"] if "Addons" in HELP else []),
+ cmd,
+ ),
+ file=inline_pic(),
+ buttons=_main_help_menu,
+ )
+ except BotResponseTimeoutError:
+ return await ult.eor(
+ get_string("help_2").format(HNDLR),
+ )
+ except BotInlineDisabledError:
+ return await ult.eor(get_string("help_3"))
+ await results[0].click(chat.id, reply_to=ult.reply_to_msg_id, hide_via=True)
+ await ult.delete()
diff --git a/plugins/_inline.py b/plugins/_inline.py
new file mode 100644
index 0000000000000000000000000000000000000000..bcda7ee726539e975a10ad783b401be2f6677a49
--- /dev/null
+++ b/plugins/_inline.py
@@ -0,0 +1,451 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+import re
+import time
+from datetime import datetime
+from os import remove
+
+from git import Repo
+from telethon import Button
+from telethon.tl.types import InputWebDocument, Message
+from telethon.utils import resolve_bot_file_id
+
+from pyUltroid._misc._assistant import callback, in_pattern
+from pyUltroid.dB._core import HELP, LIST
+from pyUltroid.fns.helper import gen_chlog, time_formatter, updater
+from pyUltroid.fns.misc import split_list
+
+from . import (
+ HNDLR,
+ LOGS,
+ OWNER_NAME,
+ InlinePlugin,
+ asst,
+ get_string,
+ inline_pic,
+ split_list,
+ start_time,
+ udB,
+)
+from ._help import _main_help_menu
+
+# ================================================#
+
+helps = get_string("inline_1")
+
+add_ons = udB.get_key("ADDONS")
+
+zhelps = get_string("inline_3") if add_ons is False else get_string("inline_2")
+PLUGINS = HELP.get("Official", [])
+ADDONS = HELP.get("Addons", [])
+upage = 0
+# ============================================#
+
+# --------------------BUTTONS--------------------#
+
+SUP_BUTTONS = [
+ [
+ Button.url("• Repo •", url="https://github.com/TeamUltroid/Ultroid"),
+ Button.url("• Support •", url="t.me/UltroidSupportChat"),
+ ],
+]
+
+# --------------------BUTTONS--------------------#
+
+
+@in_pattern(owner=True, func=lambda x: not x.text)
+async def inline_alive(o):
+ TLINK = inline_pic() or "https://graph.org/file/74d6259983e0642923fdb.jpg"
+ MSG = "• **Ultroid Userbot •**"
+ WEB0 = InputWebDocument(
+ "https://graph.org/file/acd4f5d61369f74c5e7a7.jpg", 0, "image/jpg", []
+ )
+ RES = [
+ await o.builder.article(
+ type="photo",
+ text=MSG,
+ include_media=True,
+ buttons=SUP_BUTTONS,
+ title="Ultroid Userbot",
+ description="Userbot | Telethon",
+ url=TLINK,
+ thumb=WEB0,
+ content=InputWebDocument(TLINK, 0, "image/jpg", []),
+ )
+ ]
+ await o.answer(
+ RES,
+ private=True,
+ cache_time=300,
+ switch_pm="👥 ULTROID PORTAL",
+ switch_pm_param="start",
+ )
+
+
+@in_pattern("ultd", owner=True)
+async def inline_handler(event):
+ z = []
+ for x in LIST.values():
+ z.extend(x)
+ text = get_string("inline_4").format(
+ OWNER_NAME,
+ len(HELP.get("Official", [])),
+ len(HELP.get("Addons", [])),
+ len(z),
+ )
+ if inline_pic():
+ result = await event.builder.photo(
+ file=inline_pic(),
+ link_preview=False,
+ text=text,
+ buttons=_main_help_menu,
+ )
+ else:
+ result = await event.builder.article(
+ title="Ultroid Help Menu", text=text, buttons=_main_help_menu
+ )
+ await event.answer([result], private=True, cache_time=300, gallery=True)
+
+
+@in_pattern("pasta", owner=True)
+async def _(event):
+ ok = event.text.split("-")[1]
+ link = f"https://spaceb.in/{ok}"
+ raw = f"https://spaceb.in/api/{ok}/raw"
+ result = await event.builder.article(
+ title="Paste",
+ text="Pasted to Spacebin 🌌",
+ buttons=[
+ [
+ Button.url("SpaceBin", url=link),
+ Button.url("Raw", url=raw),
+ ],
+ ],
+ )
+ await event.answer([result])
+
+
+@callback("ownr", owner=True)
+async def setting(event):
+ z = []
+ for x in LIST.values():
+ z.extend(x)
+ await event.edit(
+ get_string("inline_4").format(
+ OWNER_NAME,
+ len(HELP.get("Official", [])),
+ len(HELP.get("Addons", [])),
+ len(z),
+ ),
+ file=inline_pic(),
+ link_preview=False,
+ buttons=[
+ [
+ Button.inline("•Pɪɴɢ•", data="pkng"),
+ Button.inline("•Uᴘᴛɪᴍᴇ•", data="upp"),
+ ],
+ [
+ Button.inline("•Stats•", data="alive"),
+ Button.inline("•Uᴘᴅᴀᴛᴇ•", data="doupdate"),
+ ],
+ [Button.inline("« Bᴀᴄᴋ", data="open")],
+ ],
+ )
+
+
+_strings = {"Official": helps, "Addons": zhelps, "VCBot": get_string("inline_6")}
+
+
+@callback(re.compile("uh_(.*)"), owner=True)
+async def help_func(ult):
+ key, count = ult.data_match.group(1).decode("utf-8").split("_")
+ if key == "VCBot" and HELP.get("VCBot") is None:
+ return await ult.answer(get_string("help_12"), alert=True)
+ elif key == "Addons" and HELP.get("Addons") is None:
+ return await ult.answer(get_string("help_13").format(HNDLR), alert=True)
+ if "|" in count:
+ _, count = count.split("|")
+ count = int(count) if count else 0
+ text = _strings.get(key, "").format(OWNER_NAME, len(HELP.get(key)))
+ await ult.edit(text, buttons=page_num(count, key), link_preview=False)
+
+
+@callback(re.compile("uplugin_(.*)"), owner=True)
+async def uptd_plugin(event):
+ key, file = event.data_match.group(1).decode("utf-8").split("_")
+ index = None
+ if "|" in file:
+ file, index = file.split("|")
+ key_ = HELP.get(key, [])
+ hel_p = f"Plugin Name - `{file}`\n"
+ help_ = ""
+ try:
+ for i in key_[file]:
+ help_ += i
+ except BaseException:
+ if file in LIST:
+ help_ = get_string("help_11").format(file)
+ for d in LIST[file]:
+ help_ += HNDLR + d
+ help_ += "\n"
+ if not help_:
+ help_ = f"{file} has no Detailed Help!"
+ help_ += "\n© @TeamUltroid"
+ buttons = []
+ if inline_pic():
+ data = f"sndplug_{key}_{file}"
+ if index is not None:
+ data += f"|{index}"
+ buttons.append(
+ [
+ Button.inline(
+ "« Sᴇɴᴅ Pʟᴜɢɪɴ »",
+ data=data,
+ )
+ ]
+ )
+ data = f"uh_{key}_"
+ if index is not None:
+ data += f"|{index}"
+ buttons.append(
+ [
+ Button.inline("« Bᴀᴄᴋ", data=data),
+ ]
+ )
+ try:
+ await event.edit(help_, buttons=buttons)
+ except Exception as er:
+ LOGS.exception(er)
+ help = f"Do `{HNDLR}help {key}` to get list of commands."
+ await event.edit(help, buttons=buttons)
+
+
+@callback(data="doupdate", owner=True)
+async def _(event):
+ if not await updater():
+ return await event.answer(get_string("inline_9"), cache_time=0, alert=True)
+ if not inline_pic():
+ return await event.answer(f"Do '{HNDLR}update' to update..")
+ repo = Repo.init()
+ changelog, tl_chnglog = await gen_chlog(
+ repo, f"HEAD..upstream/{repo.active_branch}"
+ )
+ changelog_str = changelog + "\n\n" + get_string("inline_8")
+ if len(changelog_str) > 1024:
+ await event.edit(get_string("upd_4"))
+ with open("ultroid_updates.txt", "w+") as file:
+ file.write(tl_chnglog)
+ await event.edit(
+ get_string("upd_5"),
+ file="ultroid_updates.txt",
+ buttons=[
+ [Button.inline("• Uᴘᴅᴀᴛᴇ Nᴏᴡ •", data="updatenow")],
+ [Button.inline("« Bᴀᴄᴋ", data="ownr")],
+ ],
+ )
+ remove("ultroid_updates.txt")
+ else:
+ await event.edit(
+ changelog_str,
+ buttons=[
+ [Button.inline("Update Now", data="updatenow")],
+ [Button.inline("« Bᴀᴄᴋ", data="ownr")],
+ ],
+ parse_mode="html",
+ )
+
+
+@callback(data="pkng", owner=True)
+async def _(event):
+ start = datetime.now()
+ end = datetime.now()
+ ms = (end - start).microseconds
+ pin = f"🌋Pɪɴɢ = {ms} microseconds"
+ await event.answer(pin, cache_time=0, alert=True)
+
+
+@callback(data="upp", owner=True)
+async def _(event):
+ uptime = time_formatter((time.time() - start_time) * 1000)
+ pin = f"🙋Uᴘᴛɪᴍᴇ = {uptime}"
+ await event.answer(pin, cache_time=0, alert=True)
+
+
+@callback(data="inlone", owner=True)
+async def _(e):
+ _InButtons = [
+ Button.switch_inline(_, query=InlinePlugin[_], same_peer=True)
+ for _ in list(InlinePlugin.keys())
+ ]
+ InButtons = split_list(_InButtons, 2)
+
+ button = InButtons.copy()
+ button.append(
+ [
+ Button.inline("« Bᴀᴄᴋ", data="open"),
+ ],
+ )
+ await e.edit(buttons=button, link_preview=False)
+
+
+@callback(data="open", owner=True)
+async def opner(event):
+ z = []
+ for x in LIST.values():
+ z.extend(x)
+ await event.edit(
+ get_string("inline_4").format(
+ OWNER_NAME,
+ len(HELP.get("Official", [])),
+ len(HELP.get("Addons", [])),
+ len(z),
+ ),
+ buttons=_main_help_menu,
+ link_preview=False,
+ )
+
+
+@callback(data="close", owner=True)
+async def on_plug_in_callback_query_handler(event):
+ await event.edit(
+ get_string("inline_5"),
+ buttons=Button.inline("Oᴘᴇɴ Aɢᴀɪɴ", data="open"),
+ )
+
+
+def page_num(index, key):
+ rows = udB.get_key("HELP_ROWS") or 5
+ cols = udB.get_key("HELP_COLUMNS") or 2
+ loaded = HELP.get(key, [])
+ emoji = udB.get_key("EMOJI_IN_HELP") or "✘"
+ List = [
+ Button.inline(f"{emoji} {x} {emoji}", data=f"uplugin_{key}_{x}|{index}")
+ for x in sorted(loaded)
+ ]
+ all_ = split_list(List, cols)
+ fl_ = split_list(all_, rows)
+ try:
+ new_ = fl_[index]
+ except IndexError:
+ new_ = fl_[0] if fl_ else []
+ index = 0
+ if index == 0 and len(fl_) == 1:
+ new_.append([Button.inline("« Bᴀᴄᴋ »", data="open")])
+ else:
+ new_.append(
+ [
+ Button.inline(
+ "« Pʀᴇᴠɪᴏᴜs",
+ data=f"uh_{key}_{index-1}",
+ ),
+ Button.inline("« Bᴀᴄᴋ »", data="open"),
+ Button.inline(
+ "Nᴇxᴛ »",
+ data=f"uh_{key}_{index+1}",
+ ),
+ ]
+ )
+ return new_
+
+
+# --------------------------------------------------------------------------------- #
+
+
+STUFF = {}
+
+
+@in_pattern("stf(.*)", owner=True)
+async def ibuild(e):
+ n = e.pattern_match.group(1).strip()
+ builder = e.builder
+ if not (n and n.isdigit()):
+ return
+ ok = STUFF.get(int(n))
+ txt = ok.get("msg")
+ pic = ok.get("media")
+ btn = ok.get("button")
+ if not (pic or txt):
+ txt = "Hey!"
+ if pic:
+ try:
+ include_media = True
+ mime_type, _pic = None, None
+ cont, results = None, None
+ try:
+ ext = str(pic).split(".")[-1].lower()
+ except BaseException:
+ ext = None
+ if ext in ["img", "jpg", "png"]:
+ _type = "photo"
+ mime_type = "image/jpg"
+ elif ext in ["mp4", "mkv", "gif"]:
+ mime_type = "video/mp4"
+ _type = "gif"
+ else:
+ try:
+ if "telethon.tl.types" in str(type(pic)):
+ _pic = pic
+ else:
+ _pic = resolve_bot_file_id(pic)
+ except BaseException:
+ pass
+ if _pic:
+ results = [
+ await builder.document(
+ _pic,
+ title="Ultroid Op",
+ text=txt,
+ description="@TeamUltroid",
+ buttons=btn,
+ link_preview=False,
+ )
+ ]
+ else:
+ _type = "article"
+ include_media = False
+ if not results:
+ if include_media:
+ cont = InputWebDocument(pic, 0, mime_type, [])
+ results = [
+ await builder.article(
+ title="Ultroid Op",
+ type=_type,
+ text=txt,
+ description="@TeamUltroid",
+ include_media=include_media,
+ buttons=btn,
+ thumb=cont,
+ content=cont,
+ link_preview=False,
+ )
+ ]
+ return await e.answer(results)
+ except Exception as er:
+ LOGS.exception(er)
+ result = [
+ await builder.article("Ultroid Op", text=txt, link_preview=False, buttons=btn)
+ ]
+ await e.answer(result)
+
+
+async def something(e, msg, media, button, reply=True, chat=None):
+ if e.client._bot:
+ return await e.reply(msg, file=media, buttons=button)
+ num = len(STUFF) + 1
+ STUFF.update({num: {"msg": msg, "media": media, "button": button}})
+ try:
+ res = await e.client.inline_query(asst.me.username, f"stf{num}")
+ return await res[0].click(
+ chat or e.chat_id,
+ reply_to=bool(isinstance(e, Message) and reply),
+ hide_via=True,
+ silent=True,
+ )
+
+ except Exception as er:
+ LOGS.exception(er)
diff --git a/plugins/_ultroid.py b/plugins/_ultroid.py
new file mode 100644
index 0000000000000000000000000000000000000000..b2a3e2a6fb4bbf30e35f0fe5979307c2b3c145e2
--- /dev/null
+++ b/plugins/_ultroid.py
@@ -0,0 +1,66 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from telethon.errors import (
+ BotMethodInvalidError,
+ ChatSendInlineForbiddenError,
+ ChatSendMediaForbiddenError,
+)
+
+from . import LOG_CHANNEL, LOGS, Button, asst, eor, get_string, ultroid_cmd
+
+REPOMSG = """
+• **ULTROID USERBOT** •\n
+• Repo - [Click Here](https://github.com/TeamUltroid/Ultroid)
+• Addons - [Click Here](https://github.com/TeamUltroid/UltroidAddons)
+• Support - @UltroidSupportChat
+"""
+
+RP_BUTTONS = [
+ [
+ Button.url(get_string("bot_3"), "https://github.com/TeamUltroid/Ultroid"),
+ Button.url("Addons", "https://github.com/TeamUltroid/UltroidAddons"),
+ ],
+ [Button.url("Support Group", "t.me/UltroidSupportChat")],
+]
+
+ULTSTRING = """🎇 **Thanks for Deploying Ultroid Userbot!**
+
+• Here, are the Some Basic stuff from, where you can Know, about its Usage."""
+
+
+@ultroid_cmd(
+ pattern="repo$",
+ manager=True,
+)
+async def repify(e):
+ try:
+ q = await e.client.inline_query(asst.me.username, "")
+ await q[0].click(e.chat_id)
+ return await e.delete()
+ except (
+ ChatSendInlineForbiddenError,
+ ChatSendMediaForbiddenError,
+ BotMethodInvalidError,
+ ):
+ pass
+ except Exception as er:
+ LOGS.info(f"Error while repo command : {str(er)}")
+ await e.eor(REPOMSG)
+
+
+@ultroid_cmd(pattern="ultroid$")
+async def useUltroid(rs):
+ button = Button.inline("Start >>", "initft_2")
+ msg = await asst.send_message(
+ LOG_CHANNEL,
+ ULTSTRING,
+ file="https://graph.org/file/54a917cc9dbb94733ea5f.jpg",
+ buttons=button,
+ )
+ if not (rs.chat_id == LOG_CHANNEL and rs.client._bot):
+ await eor(rs, f"**[Click Here]({msg.message_link})**")
diff --git a/plugins/_userlogs.py b/plugins/_userlogs.py
new file mode 100644
index 0000000000000000000000000000000000000000..0696ce5b2edfe0b7dad6b98b6ea7e9f8ae499abb
--- /dev/null
+++ b/plugins/_userlogs.py
@@ -0,0 +1,297 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+import os
+import re
+
+from telethon.errors.rpcerrorlist import (
+ ChannelPrivateError,
+ ChatWriteForbiddenError,
+ MediaCaptionTooLongError,
+ MediaEmptyError,
+ MessageTooLongError,
+ PeerIdInvalidError,
+ UserNotParticipantError,
+)
+from telethon.tl.types import MessageEntityMention, MessageEntityMentionName, User
+from telethon.utils import get_display_name
+
+from pyUltroid.dB.botchat_db import tag_add, who_tag
+
+from . import (
+ LOG_CHANNEL,
+ LOGS,
+ Button,
+ asst,
+ callback,
+ events,
+ get_string,
+ inline_mention,
+ udB,
+ ultroid_bot,
+)
+
+CACHE_SPAM = {}
+TAG_EDITS = {}
+
+
+@ultroid_bot.on(
+ events.NewMessage(
+ incoming=True,
+ func=lambda e: (e.mentioned),
+ ),
+)
+async def all_messages_catcher(e):
+ x = await e.get_sender()
+ if isinstance(x, User) and (x.bot or x.verified):
+ return
+ if not udB.get_key("TAG_LOG"):
+ return
+ NEEDTOLOG = udB.get_key("TAG_LOG")
+ buttons = await parse_buttons(e)
+ try:
+ sent = await asst.send_message(NEEDTOLOG, e.message, buttons=buttons)
+ if TAG_EDITS.get(e.chat_id):
+ TAG_EDITS[e.chat_id].update({e.id: {"id": sent.id, "msg": e}})
+ else:
+ TAG_EDITS.update({e.chat_id: {e.id: {"id": sent.id, "msg": e}}})
+ tag_add(sent.id, e.chat_id, e.id)
+ except MediaEmptyError as er:
+ LOGS.debug(f"handling {er}.")
+ try:
+ msg = await asst.get_messages(e.chat_id, ids=e.id)
+ sent = await asst.send_message(NEEDTOLOG, msg, buttons=buttons)
+ if TAG_EDITS.get(e.chat_id):
+ TAG_EDITS[e.chat_id].update({e.id: {"id": sent.id, "msg": e}})
+ else:
+ TAG_EDITS.update({e.chat_id: {e.id: {"id": sent.id, "msg": e}}})
+ tag_add(sent.id, e.chat_id, e.id)
+ except Exception as me:
+ if not isinstance(me, (PeerIdInvalidError, ValueError)):
+ LOGS.exception(me)
+ if e.photo or e.sticker or e.gif:
+ try:
+ media = await e.download_media()
+ sent = await asst.send_message(
+ NEEDTOLOG, e.message.text, file=media, buttons=buttons
+ )
+ if TAG_EDITS.get(e.chat_id):
+ TAG_EDITS[e.chat_id].update({e.id: {"id": sent.id, "msg": e}})
+ else:
+ TAG_EDITS.update({e.chat_id: {e.id: {"id": sent.id, "msg": e}}})
+ return os.remove(media)
+ except Exception as er:
+ LOGS.exception(er)
+ await asst.send_message(NEEDTOLOG, get_string("com_4"), buttons=buttons)
+ except (PeerIdInvalidError, ValueError) as er:
+ LOGS.exception(er)
+ try:
+ CACHE_SPAM[NEEDTOLOG]
+ except KeyError:
+ await asst.send_message(
+ udB.get_key("LOG_CHANNEL"), get_string("userlogs_1")
+ )
+ CACHE_SPAM.update({NEEDTOLOG: True})
+ except ChatWriteForbiddenError:
+ try:
+ await asst.get_permissions(NEEDTOLOG, "me")
+ MSG = get_string("userlogs_4")
+ except UserNotParticipantError:
+ MSG = get_string("userlogs_2")
+ try:
+ CACHE_SPAM[NEEDTOLOG]
+ except KeyError:
+ await asst.send_message(LOG_CHANNEL, MSG)
+ CACHE_SPAM.update({NEEDTOLOG: True})
+ except Exception as er:
+ LOGS.exception(er)
+
+
+if udB.get_key("TAG_LOG"):
+
+ @ultroid_bot.on(events.MessageEdited(func=lambda x: not x.out))
+ async def upd_edits(event):
+ x = event.sender
+ if isinstance(x, User) and (x.bot or x.verified):
+ return
+ if event.chat_id not in TAG_EDITS:
+ if event.sender_id == udB.get_key("TAG_LOG"):
+ return
+ if event.is_private:
+ return
+ if entities := event.get_entities_text():
+ is_self = False
+ username = event.client.me.username
+ if username:
+ username = username.lower()
+ for ent, text in entities:
+ if isinstance(ent, MessageEntityMention):
+ is_self = text[1:].lower() == username
+ elif isinstance(ent, MessageEntityMentionName):
+ is_self = ent.user_id == event.client.me.id
+ if is_self:
+ text = f"**#Edited & #Mentioned**\n\n{event.text}"
+ try:
+ sent = await asst.send_message(
+ udB.get_key("TAG_LOG"),
+ text,
+ buttons=await parse_buttons(event),
+ )
+ except Exception as er:
+ return LOGS.exception(er)
+ if TAG_EDITS.get(event.chat_id):
+ TAG_EDITS[event.chat_id].update({event.id: {"id": sent.id}})
+ else:
+ TAG_EDITS.update({event.chat_id: {event.id: {"id": sent.id}}})
+ return
+ d_ = TAG_EDITS[event.chat_id]
+ if not d_.get(event.id):
+ return
+ d_ = d_[event.id]
+ if d_["msg"].text == event.text:
+ return
+ msg = None
+ if d_.get("count"):
+ d_["count"] += 1
+ else:
+ msg = True
+ d_.update({"count": 1})
+ if d_["count"] > 10:
+ return # some limit to take edits
+ try:
+ MSG = await asst.get_messages(udB.get_key("TAG_LOG"), ids=d_["id"])
+ except Exception as er:
+ return LOGS.exception(er)
+ TEXT = MSG.text
+ if msg:
+ TEXT += "\n\n🖋 **Later Edited to !**"
+ strf = event.edit_date.strftime("%H:%M:%S")
+ if "\n" not in event.text:
+ TEXT += f"\n• `{strf}` : {event.text}"
+ else:
+ TEXT += f"\n• `{strf}` :\n-> {event.text}"
+ if d_["count"] == 10:
+ TEXT += "\n\n• __Only the first 10 Edits are shown.__"
+ try:
+ msg = await MSG.edit(TEXT, buttons=await parse_buttons(event))
+ d_["msg"] = msg
+ except (MessageTooLongError, MediaCaptionTooLongError):
+ del TAG_EDITS[event.chat_id][event.id]
+ except Exception as er:
+ LOGS.exception(er)
+
+ @ultroid_bot.on(
+ events.NewMessage(
+ outgoing=True,
+ chats=[udB.get_key("TAG_LOG")],
+ func=lambda e: e.reply_to,
+ )
+ )
+ async def idk(e):
+ id = e.reply_to_msg_id
+ chat, msg = who_tag(id)
+ if chat and msg:
+ try:
+ await ultroid_bot.send_message(chat, e.message, reply_to=msg)
+ except BaseException as er:
+ LOGS.exception(er)
+
+
+# log for assistant/user joins/add
+
+
+async def when_added_or_joined(event):
+ user = await event.get_user()
+ chat = await event.get_chat()
+ if not (user and user.is_self):
+ return
+ if getattr(chat, "username", None):
+ chat = f"[{chat.title}](https://t.me/{chat.username}/{event.action_message.id})"
+ else:
+ chat = f"[{chat.title}](https://t.me/c/{chat.id}/{event.action_message.id})"
+ key = "bot" if event.client._bot else "user"
+ buttons = Button.inline(
+ get_string("userlogs_3"), data=f"leave_ch_{event.chat_id}|{key}"
+ )
+ if event.user_added:
+ tmp = event.added_by
+ text = f"#ADD_LOG\n\n{inline_mention(tmp)} just added {inline_mention(user)} to {chat}."
+ elif event.from_request:
+ text = f"#APPROVAL_LOG\n\n{inline_mention(user)} just got Chat Join Approval to {chat}."
+ else:
+ text = f"#JOIN_LOG\n\n{inline_mention(user)} just joined {chat}."
+ await asst.send_message(udB.get_key("LOG_CHANNEL"), text, buttons=buttons)
+
+
+asst.add_event_handler(
+ when_added_or_joined, events.ChatAction(func=lambda x: x.user_added)
+)
+ultroid_bot.add_event_handler(
+ when_added_or_joined,
+ events.ChatAction(func=lambda x: x.user_added or x.user_joined),
+)
+_client = {"bot": asst, "user": ultroid_bot}
+
+
+@callback(
+ re.compile(
+ "leave_ch_(.*)",
+ ),
+ from_users=[ultroid_bot.uid],
+)
+async def leave_ch_at(event):
+ cht = event.data_match.group(1).decode("UTF-8")
+ ch_id, client = cht.split("|")
+ try:
+ client = _client[client]
+ except KeyError:
+ return
+ try:
+ name = (await client.get_entity(int(ch_id))).title
+ await client.delete_dialog(int(ch_id))
+ except UserNotParticipantError:
+ pass
+ except ChannelPrivateError:
+ return await event.edit(
+ "`[CANT_ACCESS_CHAT]` `Maybe already left or got banned.`"
+ )
+ except Exception as er:
+ LOGS.exception(er)
+ return await event.answer(str(er))
+ await event.edit(get_string("userlogs_5").format(name))
+
+
+@callback("do_nothing")
+async def _(event):
+ await event.answer()
+
+
+async def parse_buttons(event):
+ y, x = event.chat, event.sender
+ where_n, who_n = get_display_name(y), get_display_name(x)
+ where_l = event.message_link
+ buttons = [[Button.url(where_n, where_l)]]
+ if isinstance(x, User) and x.username:
+ try:
+ buttons.append(
+ [Button.mention(who_n, await asst.get_input_entity(x.username))]
+ )
+ except Exception as er:
+ LOGS.exception(er)
+ buttons.append([Button.url(who_n, f"t.me/{x.username}")])
+ elif getattr(x, "username"):
+ buttons.append([Button.url(who_n, f"t.me/{x.username}")])
+ else:
+ buttons.append([Button.url(who_n, where_l)])
+ replied = await event.get_reply_message()
+ if replied and replied.out:
+ button = Button.url("Replied to", replied.message_link)
+ if len(who_n) > 7:
+ buttons.append([button])
+ else:
+ buttons[-1].append(button)
+ return buttons
diff --git a/plugins/_wspr.py b/plugins/_wspr.py
new file mode 100644
index 0000000000000000000000000000000000000000..f46def7dadebbc0e02e845fe53070f99224aac0a
--- /dev/null
+++ b/plugins/_wspr.py
@@ -0,0 +1,204 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+import re
+
+from telethon import Button
+from telethon.errors.rpcerrorlist import (
+ BotInlineDisabledError,
+ BotResponseTimeoutError,
+ MessageNotModifiedError,
+)
+from telethon.tl import types
+from telethon.tl.functions.users import GetFullUserRequest as gu
+
+from . import (
+ HNDLR,
+ LOGS,
+ asst,
+ callback,
+ get_string,
+ in_pattern,
+ inline_mention,
+ ultroid_bot,
+ ultroid_cmd,
+)
+
+buddhhu = {}
+
+
+@ultroid_cmd(
+ pattern="wspr( (.*)|$)",
+)
+async def _(e):
+ if e.reply_to_msg_id:
+ okk = await e.get_reply_message()
+ put = f"@{okk.sender.username}" if okk.sender.username else okk.sender_id
+ else:
+ put = e.pattern_match.group(1).strip()
+ if put:
+ try:
+ results = await e.client.inline_query(asst.me.username, f"msg {put}")
+ except BotResponseTimeoutError:
+ return await e.eor(
+ get_string("help_2").format(HNDLR),
+ )
+ except BotInlineDisabledError:
+ return await e.eor(get_string("help_3"))
+ await results[0].click(e.chat_id, reply_to=e.reply_to_msg_id, hide_via=True)
+ return await e.delete()
+ await e.eor(get_string("wspr_3"))
+
+
+@in_pattern("wspr", owner=True)
+async def _(e):
+ iuser = e.query.user_id
+ zzz = e.text.split(maxsplit=2)
+ try:
+ query = zzz[1]
+ if query.isdigit():
+ query = int(query)
+ logi = await ultroid_bot.get_entity(query)
+ if not isinstance(logi, types.User):
+ raise ValueError("Invalid Username.")
+ except IndexError:
+ sur = await e.builder.article(
+ title="Give Username",
+ description="You Didn't Type Username or id.",
+ text="You Didn't Type Username or id.",
+ )
+ return await e.answer([sur])
+ except ValueError as er:
+ LOGS.exception(er)
+ sur = await e.builder.article(
+ title="User Not Found",
+ description="Make sure username or id is correct.",
+ text="Make sure username or id is correct.",
+ )
+ return await e.answer([sur])
+ try:
+ desc = zzz[2]
+ except IndexError:
+ sur = await e.builder.article(
+ title="Type ur msg", text="You Didn't Type Your Msg"
+ )
+ return await e.answer([sur])
+ button = [
+ [
+ Button.inline("Secret Msg", data=f"dd_{e.id}"),
+ Button.inline("Delete Msg", data=f"del_{e.id}"),
+ ],
+ [
+ Button.switch_inline(
+ "New", query=f"wspr {logi.username or logi.id}", same_peer=True
+ )
+ ],
+ ]
+ us = logi.username or logi.first_name
+ sur = await e.builder.article(
+ title=logi.first_name,
+ description=desc,
+ text=get_string("wspr_1").format(us),
+ buttons=button,
+ )
+ buddhhu.update({e.id: [logi.id, iuser, desc]})
+ await e.answer([sur])
+
+
+@in_pattern("msg", owner=True)
+async def _(e):
+ zzz = e.text.split(maxsplit=1)
+ desc = "Touch me"
+ try:
+ query = zzz[1]
+ if query.isdigit():
+ query = int(query)
+ logi = await ultroid_bot(gu(id=query))
+ user = logi.users[0]
+ mention = inline_mention(user)
+ x = user.status
+ if isinstance(x, types.UserStatusOnline):
+ status = "Online"
+ elif isinstance(x, types.UserStatusOffline):
+ status = "Offline"
+ elif isinstance(x, types.UserStatusRecently):
+ status = "Last Seen Recently"
+ elif isinstance(x, types.UserStatusLastMonth):
+ status = "Last seen months ago"
+ elif isinstance(x, types.UserStatusLastWeek):
+ status = "Last seen weeks ago"
+ else:
+ status = "Can't Tell"
+ text = f"**Name:** `{user.first_name}`\n"
+ text += f"**Id:** `{user.id}`\n"
+ if user.username:
+ text += f"**Username:** `{user.username}`\n"
+ url = f"https://t.me/{user.username}"
+ else:
+ text += f"**Mention:** `{mention}`\n"
+ url = f"tg://user?id={user.id}"
+ text += f"**Status:** `{status}`\n"
+ text += f"**About:** `{logi.full_user.about}`"
+ button = [
+ Button.url("Private", url=url),
+ Button.switch_inline(
+ "Secret msg",
+ query=f"wspr {query} Hello 👋",
+ same_peer=True,
+ ),
+ ]
+ sur = e.builder.article(
+ title=user.first_name,
+ description=desc,
+ text=text,
+ buttons=button,
+ )
+ except IndexError:
+ sur = e.builder.article(
+ title="Give Username",
+ description="You Didn't Type Username or id.",
+ text="You Didn't Type Username or id.",
+ )
+ except BaseException as er:
+ LOGS.exception(er)
+ name = get_string("wspr_4").format(query)
+ sur = e.builder.article(
+ title=name,
+ text=name,
+ )
+
+ await e.answer([sur])
+
+
+@callback(
+ re.compile(
+ "dd_(.*)",
+ ),
+)
+async def _(e):
+ ids = int(e.pattern_match.group(1).strip().decode("UTF-8"))
+ if buddhhu.get(ids):
+ if e.sender_id in buddhhu[ids]:
+ await e.answer(buddhhu[ids][-1], alert=True)
+ else:
+ await e.answer("Not For You", alert=True)
+ else:
+ await e.answer(get_string("wspr_2"), alert=True)
+
+
+@callback(re.compile("del_(.*)"))
+async def _(e):
+ ids = int(e.pattern_match.group(1).strip().decode("UTF-8"))
+ if buddhhu.get(ids):
+ if e.sender_id in buddhhu[ids]:
+ buddhhu.pop(ids)
+ try:
+ await e.edit(get_string("wspr_2"))
+ except MessageNotModifiedError:
+ pass
+ else:
+ await e.answer(get_string("wspr_5"), alert=True)
diff --git a/plugins/admintools.py b/plugins/admintools.py
new file mode 100644
index 0000000000000000000000000000000000000000..0d402ff2d6a220a1d884460ae595012a97d4e47a
--- /dev/null
+++ b/plugins/admintools.py
@@ -0,0 +1,472 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_admintools")
+
+import asyncio
+
+from telethon.errors import BadRequestError
+from telethon.errors.rpcerrorlist import ChatNotModifiedError, UserIdInvalidError
+from telethon.tl.functions.channels import EditAdminRequest, GetFullChannelRequest
+from telethon.tl.functions.messages import GetFullChatRequest, SetHistoryTTLRequest
+from telethon.tl.types import InputMessagesFilterPinned
+from telethon.utils import get_display_name
+
+from pyUltroid.dB import DEVLIST
+from pyUltroid.fns.admins import ban_time
+from pyUltroid.fns.info import get_uinfo
+
+from . import HNDLR, LOGS, eod, eor, get_string, inline_mention, types, ultroid_cmd
+
+
+@ultroid_cmd(
+ pattern="promote( (.*)|$)",
+ admins_only=True,
+ manager=True,
+ require="add_admins",
+ fullsudo=True,
+)
+async def prmte(ult):
+ xx = await ult.eor(get_string("com_1"))
+ user, rank = await get_uinfo(ult)
+ rank = rank or "Admin"
+ FullRight = False
+ if not user:
+ return await xx.edit(get_string("pro_1"))
+ if rank.split()[0] == "-f":
+ try:
+ rank = rank.split(maxsplit=1)[1]
+ except IndexError:
+ rank = "Admin"
+ FullRight = True
+ try:
+ if FullRight:
+ await ult.client(
+ EditAdminRequest(ult.chat_id, user.id, ult.chat.admin_rights, rank)
+ )
+ else:
+ await ult.client.edit_admin(
+ ult.chat_id,
+ user.id,
+ invite_users=True,
+ ban_users=True,
+ delete_messages=True,
+ pin_messages=True,
+ manage_call=True,
+ title=rank,
+ )
+ await eod(
+ xx, get_string("pro_2").format(inline_mention(user), ult.chat.title, rank)
+ )
+ except Exception as ex:
+ return await xx.edit(f"`{ex}`")
+
+
+@ultroid_cmd(
+ pattern="demote( (.*)|$)",
+ admins_only=True,
+ manager=True,
+ require="add_admins",
+ fullsudo=True,
+)
+async def dmote(ult):
+ xx = await ult.eor(get_string("com_1"))
+ user, rank = await get_uinfo(ult)
+ if not rank:
+ rank = "Not Admin"
+ if not user:
+ return await xx.edit(get_string("de_1"))
+ try:
+ await ult.client.edit_admin(
+ ult.chat_id,
+ user.id,
+ invite_users=None,
+ ban_users=None,
+ delete_messages=None,
+ pin_messages=None,
+ manage_call=None,
+ title=rank,
+ )
+ await eod(xx, get_string("de_2").format(inline_mention(user), ult.chat.title))
+ except Exception as ex:
+ return await xx.edit(f"`{ex}`")
+
+
+@ultroid_cmd(
+ pattern="ban( (.*)|$)",
+ admins_only=True,
+ manager=True,
+ require="ban_users",
+ fullsudo=True,
+)
+async def bban(ult):
+ something = await get_uinfo(ult)
+ if not something:
+ return
+ user, reason = something
+ if not user:
+ return await eod(ult, get_string("ban_1"))
+ if user.id in DEVLIST:
+ return await eod(ult, get_string("ban_2"))
+ try:
+ await ult.client.edit_permissions(ult.chat_id, user.id, view_messages=False)
+ except UserIdInvalidError:
+ return await eod(ult, get_string("adm_1"))
+ except BadRequestError:
+ return await eod(ult, get_string("ban_3"))
+ senderme = inline_mention(await ult.get_sender())
+ userme = inline_mention(user)
+ text = get_string("ban_4").format(userme, senderme, ult.chat.title)
+ if reason:
+ text += get_string("ban_5").format(reason)
+ await eod(ult, text)
+
+
+@ultroid_cmd(
+ pattern="unban( (.*)|$)",
+ admins_only=True,
+ manager=True,
+ require="ban_users",
+ fullsudo=True,
+)
+async def uunban(ult):
+ xx = await ult.eor(get_string("com_1"))
+ if ult.text[1:].startswith("unbanall"):
+ return
+ something = await get_uinfo(ult)
+ if not something:
+ return
+ user, reason = something
+ if not user:
+ return await xx.edit(get_string("unban_1"))
+ try:
+ await ult.client.edit_permissions(ult.chat_id, user.id, view_messages=True)
+ except UserIdInvalidError:
+ return await eod(ult, get_string("adm_1"))
+ except BadRequestError:
+ return await xx.edit(get_string("adm_2"))
+ sender = inline_mention(await ult.get_sender())
+ text = get_string("unban_3").format(inline_mention(user), sender, ult.chat.title)
+ if reason:
+ text += get_string("ban_5").format(reason)
+ await xx.edit(text)
+
+
+@ultroid_cmd(
+ pattern="kick( (.*)|$)",
+ manager=True,
+ require="ban_users",
+ fullsudo=True,
+)
+async def kck(ult):
+ if "kickme" in ult.text:
+ return
+ if ult.is_private:
+ return await ult.eor("`Use this in Group/Channel.`", time=5)
+ ml = ult.text.split(" ", maxsplit=1)[0]
+ xx = await ult.eor(get_string("com_1"))
+ something = await get_uinfo(ult)
+ if not something:
+ return
+ user, reason = something
+ if not user:
+ return await xx.edit(get_string("adm_1"))
+ if user.id in DEVLIST:
+ return await xx.edit(get_string("kick_2"))
+ if getattr(user, "is_self", False):
+ return await xx.edit(get_string("kick_3"))
+ try:
+ await ult.client.kick_participant(ult.chat_id, user.id)
+ except BadRequestError as er:
+ LOGS.info(er)
+ return await xx.edit(get_string("kick_1"))
+ except Exception as e:
+ LOGS.exception(e)
+ return
+ text = get_string("kick_4").format(
+ inline_mention(user), inline_mention(await ult.get_sender()), ult.chat.title
+ )
+ if reason:
+ text += get_string("ban_5").format(reason)
+ await xx.edit(text)
+
+
+@ultroid_cmd(
+ pattern="tban( (.*)|$)",
+ admins_only=True,
+ manager=True,
+ require="ban_users",
+ fullsudo=True,
+)
+async def tkicki(e):
+ huh = e.text.split()
+ inputt = None
+ try:
+ tme = huh[1]
+ except IndexError:
+ return await e.eor(get_string("adm_3"), time=15)
+ try:
+ inputt = huh[2]
+ except IndexError:
+ if e.reply_to_msg_id:
+ inputt = (await e.get_reply_message()).sender_id
+ if not inputt:
+ return await e.eor(get_string("tban_1"))
+ userid = await e.client.parse_id(inputt)
+ try:
+ user = await e.client.get_entity(userid)
+ except Exception as ex:
+ return await eor(e, f"`{ex}`")
+ try:
+ bun = ban_time(tme)
+ await e.client.edit_permissions(
+ e.chat_id, user.id, until_date=bun, view_messages=False
+ )
+ await eod(
+ e,
+ get_string("tban_2").format(inline_mention(user), e.chat.title, tme),
+ time=15,
+ )
+ except Exception as m:
+ return await e.eor(str(m))
+
+
+@ultroid_cmd(pattern="pin$", manager=True, require="pin_messages", fullsudo=True)
+async def pin(msg):
+ if not msg.is_reply:
+ return await eor(msg, get_string("pin_1"))
+ me = await msg.get_reply_message()
+ if me.is_private:
+ text = "`Pinned.`"
+ else:
+ text = f"Pinned [This Message]({me.message_link}) !"
+ try:
+ await msg.client.pin_message(msg.chat_id, me.id, notify=False)
+ except BadRequestError:
+ return await eor(msg, get_string("adm_2"))
+ except Exception as e:
+ return await eor(msg, f"**ERROR:**`{e}`")
+ await eor(msg, text)
+
+
+@ultroid_cmd(
+ pattern="unpin($| (.*))",
+ manager=True,
+ require="pin_messages",
+ fullsudo=True,
+)
+async def unp(ult):
+ xx = await ult.eor(get_string("com_1"))
+ ch = (ult.pattern_match.group(1).strip()).strip()
+ msg = None
+ if ult.is_reply:
+ msg = ult.reply_to_msg_id
+ elif ch != "all":
+ return await xx.edit(get_string("unpin_1").format(HNDLR))
+ try:
+ await ult.client.unpin_message(ult.chat_id, msg)
+ except BadRequestError:
+ return await xx.edit(get_string("adm_2"))
+ except Exception as e:
+ return await xx.edit(f"**ERROR:**`{e}`")
+ await xx.edit("`Unpinned!`")
+
+
+@ultroid_cmd(
+ pattern="tpin( (.*)|$)",
+ admins_only=True,
+ manager=True,
+ require="pin_messages",
+ fullsudo=True,
+)
+async def pin_message(ult):
+ match = ult.pattern_match.group(1).strip()
+ if not ult.is_reply:
+ return await ult.eor("`Reply to message..`", time=6)
+ if not match:
+ return await ult.eor("`Please provide time..`", time=8)
+ msg = await ult.eor(get_string("com_1"))
+ msg_id = ult.reply_to_msg_id
+ try:
+ time = ban_time(match)
+ await ult.client.pin_message(ult.chat_id, msg_id)
+ await msg.eor(f"`pinned for time` `{time}`", time=8)
+ except Exception as er:
+ return await msg.edit(str(er))
+ await asyncio.sleep(time)
+ try:
+ await ult.client.unpin_message(ult.chat_id, msg_id)
+ except Exception as er:
+ LOGS.exception(er)
+
+
+@ultroid_cmd(pattern="purge( (.*)|$)", manager=True, require="delete_messages")
+async def fastpurger(purg):
+ match = purg.pattern_match.group(1).strip()
+ try:
+ ABC = purg.text[6]
+ except IndexError:
+ ABC = None
+ if ABC and purg.text[6] in ["m", "a"]:
+ return
+ if not purg._client._bot and (
+ (match)
+ or (purg.is_reply and (purg.is_private or isinstance(purg.chat, types.Chat)))
+ ):
+ p = 0
+ async for msg in purg.client.iter_messages(
+ purg.chat_id,
+ limit=int(match) if match else None,
+ min_id=purg.reply_to_msg_id if purg.is_reply else None,
+ ):
+ await msg.delete()
+ p += 0
+ return await eor(purg, f"Purged {p} Messages! ", time=5)
+ if not purg.reply_to_msg_id:
+ return await eor(purg, get_string("purge_1"), time=10)
+ try:
+ await purg.client.delete_messages(
+ purg.chat_id, list(range(purg.reply_to_msg_id, purg.id))
+ )
+
+ except Exception as er:
+ LOGS.info(er)
+ await purg.eor("__Fast purge complete!__", time=5)
+
+
+@ultroid_cmd(
+ pattern="purgeme( (.*)|$)",
+)
+async def fastpurgerme(purg):
+ if num := purg.pattern_match.group(1).strip():
+ try:
+ nnt = int(num)
+ except BaseException:
+ await eor(purg, get_string("com_3"), time=5)
+ return
+ mp = 0
+ async for mm in purg.client.iter_messages(
+ purg.chat_id, limit=nnt, from_user="me"
+ ):
+ await mm.delete()
+ mp += 1
+ await eor(purg, f"Purged {mp} Messages!", time=5)
+ return
+ elif not purg.reply_to_msg_id:
+ return await eod(
+ purg,
+ "`Reply to a message to purge from or use it like ``purgeme `",
+ time=10,
+ )
+ chat = await purg.get_input_chat()
+ msgs = []
+ async for msg in purg.client.iter_messages(
+ chat,
+ from_user="me",
+ min_id=purg.reply_to_msg_id,
+ ):
+ msgs.append(msg)
+ if msgs:
+ await purg.client.delete_messages(chat, msgs)
+ await purg.eor(
+ "__Fast purge complete!__\n**Purged** `" + str(len(msgs)) + "` **messages.**",
+ time=5,
+ )
+
+
+@ultroid_cmd(
+ pattern="purgeall$",
+)
+async def _(e):
+ if not e.is_reply:
+ return await eod(
+ e,
+ get_string("purgeall_1"),
+ )
+
+ msg = await e.get_reply_message()
+ name = msg.sender
+ try:
+ await e.client.delete_messages(e.chat_id, from_user=msg.sender_id)
+ await e.eor(get_string("purgeall_2").format(name.first_name), time=5)
+ except Exception as er:
+ return await e.eor(str(er), time=5)
+
+
+@ultroid_cmd(pattern="pinned", manager=True, groups_only=True)
+async def djshsh(event):
+ chat = await event.get_chat()
+ if isinstance(chat, types.Chat):
+ FChat = await event.client(GetFullChatRequest(chat.id))
+ elif isinstance(chat, types.Channel):
+ FChat = await event.client(GetFullChannelRequest(chat.id))
+ else:
+ return
+ msg_id = FChat.full_chat.pinned_msg_id
+ if not msg_id:
+ return await event.eor(get_string("pinned_1"))
+ msg = await event.client.get_messages(chat.id, ids=msg_id)
+ if msg:
+ await event.eor(get_string("pinned_2").format(msg.message_link))
+
+
+@ultroid_cmd(
+ pattern="listpinned$",
+)
+async def get_all_pinned(event):
+ x = await event.eor(get_string("com_1"))
+ chat_id = (str(event.chat_id)).replace("-100", "")
+ chat_name = get_display_name(event.chat)
+ a = ""
+ c = 1
+ async for i in event.client.iter_messages(
+ event.chat_id, filter=InputMessagesFilterPinned
+ ):
+ if i.message:
+ t = " ".join(i.message.split()[:4])
+ txt = f"{t}...."
+ else:
+ txt = "Go to message."
+ a += f"{c}. {txt}\n"
+ c += 1
+
+ if c == 1:
+ m = f"The pinned message in {chat_name}:\n\n"
+ else:
+ m = f"List of pinned message(s) in {chat_name}:\n\n"
+
+ if not a:
+ return await eor(x, get_string("listpin_1"), time=5)
+
+ await x.edit(m + a, parse_mode="html")
+
+
+@ultroid_cmd(
+ pattern="autodelete( (.*)|$)",
+ admins_only=True,
+)
+async def autodelte(ult):
+ match = ult.pattern_match.group(1).strip()
+ if not match or match not in ["24h", "7d", "1m", "off"]:
+ return await ult.eor("`Please Use in Proper Format..`", time=5)
+ if match == "24h":
+ tt = 3600 * 24
+ elif match == "7d":
+ tt = 3600 * 24 * 7
+ elif match == "1m":
+ tt = 3600 * 24 * 31
+ else:
+ tt = 0
+ try:
+ await ult.client(SetHistoryTTLRequest(ult.chat_id, period=tt))
+ except ChatNotModifiedError:
+ return await ult.eor(
+ f"Auto Delete Setting is Already same to `{match}`", time=5
+ )
+ await ult.eor(f"Auto Delete Status Changed to `{match}` !")
diff --git a/plugins/afk.py b/plugins/afk.py
new file mode 100644
index 0000000000000000000000000000000000000000..830136a449f960298a7a45fe2f4e6c717df31615
--- /dev/null
+++ b/plugins/afk.py
@@ -0,0 +1,166 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_afk")
+
+
+import asyncio
+
+from telegraph import upload_file as uf
+from telethon import events
+
+from pyUltroid.dB.afk_db import add_afk, del_afk, is_afk
+from pyUltroid.dB.base import KeyManager
+
+from . import (
+ LOG_CHANNEL,
+ NOSPAM_CHAT,
+ Redis,
+ asst,
+ get_string,
+ mediainfo,
+ udB,
+ ultroid_bot,
+ ultroid_cmd,
+)
+
+old_afk_msg = []
+
+is_approved = KeyManager("PMPERMIT", cast=list).contains
+
+
+@ultroid_cmd(pattern="afk( (.*)|$)", owner_only=True)
+async def set_afk(event):
+ if event.client._bot or is_afk():
+ return
+ text, media, media_type = None, None, None
+ if event.pattern_match.group(1).strip():
+ text = event.text.split(maxsplit=1)[1]
+ reply = await event.get_reply_message()
+ if reply:
+ if reply.text and not text:
+ text = reply.text
+ if reply.media:
+ media_type = mediainfo(reply.media)
+ if media_type.startswith(("pic", "gif")):
+ file = await event.client.download_media(reply.media)
+ iurl = uf(file)
+ media = f"https://graph.org{iurl[0]}"
+ else:
+ media = reply.file.id
+ await event.eor("`Done`", time=2)
+ add_afk(text, media_type, media)
+ ultroid_bot.add_handler(remove_afk, events.NewMessage(outgoing=True))
+ ultroid_bot.add_handler(
+ on_afk,
+ events.NewMessage(
+ incoming=True, func=lambda e: bool(e.mentioned or e.is_private)
+ ),
+ )
+ msg1, msg2 = None, None
+ if text and media:
+ if "sticker" in media_type:
+ msg1 = await ultroid_bot.send_file(event.chat_id, file=media)
+ msg2 = await ultroid_bot.send_message(
+ event.chat_id, get_string("afk_5").format(text)
+ )
+ else:
+ msg1 = await ultroid_bot.send_message(
+ event.chat_id, get_string("afk_5").format(text), file=media
+ )
+ elif media:
+ if "sticker" in media_type:
+ msg1 = await ultroid_bot.send_file(event.chat_id, file=media)
+ msg2 = await ultroid_bot.send_message(event.chat_id, get_string("afk_6"))
+ else:
+ msg1 = await ultroid_bot.send_message(
+ event.chat_id, get_string("afk_6"), file=media
+ )
+ elif text:
+ msg1 = await event.respond(get_string("afk_5").format(text))
+ else:
+ msg1 = await event.respond(get_string("afk_6"))
+ old_afk_msg.append(msg1)
+ if msg2:
+ old_afk_msg.append(msg2)
+ return await asst.send_message(LOG_CHANNEL, msg2.text)
+ await asst.send_message(LOG_CHANNEL, msg1.text)
+
+
+async def remove_afk(event):
+ if event.is_private and udB.get_key("PMSETTING") and not is_approved(event.chat_id):
+ return
+ elif "afk" in event.text.lower():
+ return
+ elif event.chat_id in NOSPAM_CHAT:
+ return
+ if is_afk():
+ _, _, _, afk_time = is_afk()
+ del_afk()
+ off = await event.reply(get_string("afk_1").format(afk_time))
+ await asst.send_message(LOG_CHANNEL, get_string("afk_2").format(afk_time))
+ for x in old_afk_msg:
+ try:
+ await x.delete()
+ except BaseException:
+ pass
+ await asyncio.sleep(10)
+ await off.delete()
+
+
+async def on_afk(event):
+ if event.is_private and Redis("PMSETTING") and not is_approved(event.chat_id):
+ return
+ elif "afk" in event.text.lower():
+ return
+ elif not is_afk():
+ return
+ if event.chat_id in NOSPAM_CHAT:
+ return
+ sender = await event.get_sender()
+ if sender.bot or sender.verified:
+ return
+ text, media_type, media, afk_time = is_afk()
+ msg1, msg2 = None, None
+ if text and media:
+ if "sticker" in media_type:
+ msg1 = await event.reply(file=media)
+ msg2 = await event.reply(get_string("afk_3").format(afk_time, text))
+ else:
+ msg1 = await event.reply(
+ get_string("afk_3").format(afk_time, text), file=media
+ )
+ elif media:
+ if "sticker" in media_type:
+ msg1 = await event.reply(file=media)
+ msg2 = await event.reply(get_string("afk_4").format(afk_time))
+ else:
+ msg1 = await event.reply(get_string("afk_4").format(afk_time), file=media)
+ elif text:
+ msg1 = await event.reply(get_string("afk_3").format(afk_time, text))
+ else:
+ msg1 = await event.reply(get_string("afk_4").format(afk_time))
+ for x in old_afk_msg:
+ try:
+ await x.delete()
+ except BaseException:
+ pass
+ old_afk_msg.append(msg1)
+ if msg2:
+ old_afk_msg.append(msg2)
+
+
+if udB.get_key("AFK_DB"):
+ ultroid_bot.add_handler(remove_afk, events.NewMessage(outgoing=True))
+ ultroid_bot.add_handler(
+ on_afk,
+ events.NewMessage(
+ incoming=True, func=lambda e: bool(e.mentioned or e.is_private)
+ ),
+ )
diff --git a/plugins/afscrp.py b/plugins/afscrp.py
new file mode 100644
index 0000000000000000000000000000000000000000..56f02a5de24c38bbb0dd38879a80457f4eda6bc5
--- /dev/null
+++ b/plugins/afscrp.py
@@ -0,0 +1,95 @@
+import logging
+from bs4 import BeautifulSoup
+from googleapiclient.discovery import build
+from . import ultroid_cmd, async_searcher, run_async, LOGS
+import asyncio
+from io import BytesIO
+
+logging.getLogger("googleapiclient.discovery_cache").setLevel(logging.WARNING)
+
+async def fetch_full_content(url):
+ try:
+ api_url = f"https://scraper.api.airforce/scrape?url={url}"
+ response = await async_searcher(api_url)
+
+ soup = BeautifulSoup(response, "html.parser")
+ main_content = soup.select_one("article") or soup.select_one("main") or soup
+ paragraphs = [
+ para.get_text(separator=" ").strip()
+ for para in main_content.find_all("p")
+ if len(para.get_text(strip=True)) > 30
+ and not any(
+ keyword in para.get_text().lower()
+ for keyword in [
+ "privacy",
+ "cookie",
+ "subscribe",
+ "sign up",
+ "terms",
+ "all rights reserved",
+ "see all",
+ "see more",
+ ]
+ )
+ ]
+ full_text = (
+ " ".join(paragraphs[:5]) if paragraphs else "No main content available."
+ )
+ return full_text
+ except Exception as e:
+ return f"Error fetching content: {e}"
+
+async def google_search(query):
+ api_key = " AIzaSyCDOnsWu0cF8W-6jnWceUSHeuSmpC7b2g0 "
+ cse_id = "a44275f02ca2946da"
+ service = build("customsearch", "v1", developerKey=api_key)
+
+ results = service.cse().list(q=query, cx=cse_id, gl="AU").execute()
+ search_items = results.get("items", [])
+
+ search_results = await asyncio.gather(
+ *(fetch_search_result(item) for item in search_items)
+ )
+
+ return search_results
+
+async def fetch_search_result(item):
+ title = item.get("title")
+ link = item.get("link")
+ snippet = item.get("snippet")
+ full_content = await fetch_full_content(link)
+ return (title, link, snippet, full_content)
+
+async def display_readable_results(results):
+ readable_res = ""
+ for idx, result in enumerate(results, start=1):
+ title, link, snippet, full_content = result
+ full_content = (
+ full_content if full_content else "No additional content available."
+ )
+ readable_res += f"Result {idx}:\n"
+ readable_res += f"Title: {title}\n"
+ readable_res += f"Link: {link}\n"
+ readable_res += f"Snippet: {snippet}\n"
+ readable_res += f"Full Content: {full_content.strip()}\n"
+ readable_res += "\n" + "=" * 80 + "\n"
+ return readable_res
+
+@ultroid_cmd(pattern="afscrp(?: (.*)|$)")
+async def google_search_cmd(event):
+ query = event.pattern_match.group(1)
+ if not query:
+ return await event.eor("Please provide a query to search.")
+ moi = await event.eor("Searching Google...")
+ results = await google_search(query)
+ readable_results = await display_readable_results(results)
+
+ if len(readable_results) < 4095:
+ await moi.edit(readable_results)
+ else:
+ with BytesIO(readable_results.encode()) as file:
+ file.name = "google_search_results.txt"
+ await event.client.send_file(
+ event.chat_id, file, caption=f"Search results for: {query}", reply_to=event.reply_to_msg_id
+ )
+ await moi.delete()
diff --git a/plugins/antiflood.py b/plugins/antiflood.py
new file mode 100644
index 0000000000000000000000000000000000000000..82225c16956e7096bb3e05457ef1892fa14541ef
--- /dev/null
+++ b/plugins/antiflood.py
@@ -0,0 +1,121 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_antiflood")
+
+
+import re
+
+from telethon.events import NewMessage as NewMsg
+
+from pyUltroid.dB import DEVLIST
+from pyUltroid.dB.antiflood_db import get_flood, get_flood_limit, rem_flood, set_flood
+from pyUltroid.fns.admins import admin_check
+
+from . import Button, Redis, asst, callback, eod, get_string, ultroid_bot, ultroid_cmd
+
+_check_flood = {}
+
+if Redis("ANTIFLOOD"):
+
+ @ultroid_bot.on(
+ NewMsg(
+ chats=list(get_flood().keys()),
+ ),
+ )
+ async def flood_checm(event):
+ count = 1
+ chat = (await event.get_chat()).title
+ if event.chat_id in _check_flood.keys():
+ if event.sender_id == list(_check_flood[event.chat_id].keys())[0]:
+ count = _check_flood[event.chat_id][event.sender_id]
+ _check_flood[event.chat_id] = {event.sender_id: count + 1}
+ else:
+ _check_flood[event.chat_id] = {event.sender_id: count}
+ else:
+ _check_flood[event.chat_id] = {event.sender_id: count}
+ if await admin_check(event, silent=True) or getattr(event.sender, "bot", None):
+ return
+ if event.sender_id in DEVLIST:
+ return
+ if _check_flood[event.chat_id][event.sender_id] >= int(
+ get_flood_limit(event.chat_id)
+ ):
+ try:
+ name = event.sender.first_name
+ await event.client.edit_permissions(
+ event.chat_id, event.sender_id, send_messages=False
+ )
+ del _check_flood[event.chat_id]
+ await event.reply(f"#AntiFlood\n\n{get_string('antiflood_3')}")
+ await asst.send_message(
+ int(Redis("LOG_CHANNEL")),
+ f"#Antiflood\n\n`Muted `[{name}](tg://user?id={event.sender_id})` in {chat}`",
+ buttons=Button.inline(
+ "Unmute", data=f"anti_{event.sender_id}_{event.chat_id}"
+ ),
+ )
+ except BaseException:
+ pass
+
+
+@callback(
+ re.compile(
+ "anti_(.*)",
+ ),
+)
+async def unmuting(e):
+ ino = (e.data_match.group(1)).decode("UTF-8").split("_")
+ user = int(ino[0])
+ chat = int(ino[1])
+ user_name = (await ultroid_bot.get_entity(user)).first_name
+ chat_title = (await ultroid_bot.get_entity(chat)).title
+ await ultroid_bot.edit_permissions(chat, user, send_messages=True)
+ await e.edit(
+ f"#Antiflood\n\n`Unmuted `[{user_name}](tg://user?id={user})` in {chat_title}`"
+ )
+
+
+@ultroid_cmd(
+ pattern="setflood ?(\\d+)",
+ admins_only=True,
+)
+async def setflood(e):
+ input_ = e.pattern_match.group(1).strip()
+ if not input_:
+ return await e.eor("`What?`", time=5)
+ if not input_.isdigit():
+ return await e.eor(get_string("com_3"), time=5)
+ if m := set_flood(e.chat_id, input_):
+ return await eod(e, get_string("antiflood_4").format(input_))
+
+
+@ultroid_cmd(
+ pattern="remflood$",
+ admins_only=True,
+)
+async def remove_flood(e):
+ hmm = rem_flood(e.chat_id)
+ try:
+ del _check_flood[e.chat_id]
+ except BaseException:
+ pass
+ if hmm:
+ return await e.eor(get_string("antiflood_1"), time=5)
+ await e.eor(get_string("antiflood_2"), time=5)
+
+
+@ultroid_cmd(
+ pattern="getflood$",
+ admins_only=True,
+)
+async def getflood(e):
+ if ok := get_flood_limit(e.chat_id):
+ return await e.eor(get_string("antiflood_5").format(ok), time=5)
+ await e.eor(get_string("antiflood_2"), time=5)
diff --git a/plugins/asstcmd.py b/plugins/asstcmd.py
new file mode 100644
index 0000000000000000000000000000000000000000..b88446ef7d5e50d4578c2f59e6742e90fd06f89e
--- /dev/null
+++ b/plugins/asstcmd.py
@@ -0,0 +1,107 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_asstcmd")
+
+import os
+
+from pyUltroid.dB.asstcmd_db import add_cmd, cmd_reply, list_cmds, rem_cmd
+from pyUltroid.fns.tools import create_tl_btn, format_btn, get_msg_button
+
+try:
+ from telegraph import upload_file as uf
+except ImportError:
+ uf = None
+from telethon import events, utils
+
+from . import asst, get_string, mediainfo, udB, ultroid_cmd
+
+
+@ultroid_cmd(pattern="addcmd( (.*)|$)")
+async def ac(e):
+ wrd = (e.pattern_match.group(1).strip()).lower()
+ wt = await e.get_reply_message()
+ if not (wt and wrd):
+ return await e.eor(get_string("asstcmd_1"), time=5)
+ if "/" in wrd:
+ wrd = wrd.replace("/", "")
+ btn = format_btn(wt.buttons) if wt.buttons else None
+ if wt and wt.media:
+ wut = mediainfo(wt.media)
+ if wut.startswith(("pic", "gif")):
+ dl = await e.client.download_media(wt.media)
+ variable = uf(dl)
+ os.remove(dl)
+ m = f"https://graph.org{variable[0]}"
+ elif wut == "video":
+ if wt.media.document.size > 8 * 1000 * 1000:
+ return await e.eor(get_string("com_4"), time=5)
+ dl = await e.client.download_media(wt.media)
+ variable = uf(dl)
+ os.remove(dl)
+ m = f"https://graph.org{variable[0]}"
+ else:
+ m = utils.pack_bot_file_id(wt.media)
+ if wt.text:
+ txt = wt.text
+ if not btn:
+ txt, btn = get_msg_button(wt.text)
+ add_cmd(wrd, txt, m, btn)
+ else:
+ add_cmd(wrd, None, m, btn)
+ else:
+ txt = wt.text
+ if not btn:
+ txt, btn = get_msg_button(wt.text)
+ add_cmd(wrd, txt, None, btn)
+ asst.add_handler(
+ astcmds,
+ events.NewMessage(
+ func=lambda x: x.text.startswith("/") and x.text[1:] in list(list_cmds())
+ ),
+ )
+ await e.eor(get_string("asstcmd_4").format(wrd))
+
+
+@ultroid_cmd(pattern="remcmd( (.*)|$)")
+async def rc(e):
+ wrd = (e.pattern_match.group(1).strip()).lower()
+ if not wrd:
+ return await e.eor(get_string("asstcmd_2"), time=5)
+ wrd = wrd.replace("/", "")
+ rem_cmd(wrd)
+ await e.eor(get_string("asstcmd_3").format(wrd))
+
+
+@ultroid_cmd(pattern="listcmd$")
+async def lscmd(e):
+ if list_cmds():
+ ok = get_string("asstcmd_6")
+ for x in list_cmds():
+ ok += f"/{x}" + "\n"
+ return await e.eor(ok)
+ return await e.eor(get_string("asstcmd_5"))
+
+
+async def astcmds(e):
+ xx = (e.text.replace("/", "")).lower().split()[0]
+ if cmd_reply(xx):
+ msg, media, bt = cmd_reply(xx)
+ if bt:
+ bt = create_tl_btn(bt)
+ await e.reply(msg, file=media, buttons=bt)
+
+
+if udB.get_key("ASST_CMDS"):
+ asst.add_handler(
+ astcmds,
+ events.NewMessage(
+ func=lambda x: x.text.startswith("/") and x.text[1:] in list(list_cmds())
+ ),
+ )
diff --git a/plugins/audiotools.py b/plugins/audiotools.py
new file mode 100644
index 0000000000000000000000000000000000000000..f8c0b52558cc3642647a2145d8693182305a6c98
--- /dev/null
+++ b/plugins/audiotools.py
@@ -0,0 +1,160 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+
+import os
+import time
+from datetime import datetime as dt
+
+from pyUltroid.fns.tools import set_attributes
+
+from . import (
+ LOGS,
+ ULTConfig,
+ bash,
+ downloader,
+ eod,
+ eor,
+ genss,
+ get_help,
+ get_string,
+ humanbytes,
+ mediainfo,
+ stdr,
+ time_formatter,
+ ultroid_cmd,
+ uploader,
+)
+
+__doc__ = get_help("help_audiotools")
+
+
+@ultroid_cmd(pattern="makevoice$")
+async def vnc(e):
+ if not e.reply_to:
+ return await eod(e, get_string("audiotools_1"))
+ r = await e.get_reply_message()
+ if not mediainfo(r.media).startswith(("audio", "video")):
+ return await eod(e, get_string("spcltool_1"))
+ xxx = await e.eor(get_string("com_1"))
+ file, _ = await e.client.fast_downloader(
+ r.document,
+ )
+ await xxx.edit(get_string("audiotools_2"))
+ await bash(
+ f"ffmpeg -i '{file.name}' -map 0:a -codec:a libopus -b:a 100k -vbr on out.opus"
+ )
+ try:
+ await e.client.send_message(
+ e.chat_id, file="out.opus", force_document=False, reply_to=r
+ )
+ except Exception as er:
+ LOGS.exception(er)
+ return await xxx.edit("`Failed to convert in Voice...`")
+ await xxx.delete()
+ os.remove(file.name)
+ os.remove("out.opus")
+
+
+@ultroid_cmd(pattern="atrim( (.*)|$)")
+async def trim_aud(e):
+ sec = e.pattern_match.group(1).strip()
+ if not sec or "-" not in sec:
+ return await eod(e, get_string("audiotools_3"))
+ a, b = sec.split("-")
+ if int(a) >= int(b):
+ return await eod(e, get_string("audiotools_4"))
+ vido = await e.get_reply_message()
+ if vido and vido.media and mediainfo(vido.media).startswith(("video", "audio")):
+ if hasattr(vido.media, "document"):
+ vfile = vido.media.document
+ name = vido.file.name
+ else:
+ vfile = vido.media
+ name = ""
+ if not name:
+ name = dt.now().isoformat("_", "seconds") + ".mp4"
+ xxx = await e.eor(get_string("audiotools_5"))
+ c_time = time.time()
+ file = await downloader(
+ f"resources/downloads/{name}",
+ vfile,
+ xxx,
+ c_time,
+ f"Downloading {name}...",
+ )
+
+ o_size = os.path.getsize(file.name)
+ d_time = time.time()
+ diff = time_formatter((d_time - c_time) * 1000)
+ file_name = (file.name).split("/")[-1]
+ out = file_name.replace(file_name.split(".")[-1], "_trimmed.aac")
+ if int(b) > int(await genss(file.name)):
+ os.remove(file.name)
+ return await eod(xxx, get_string("audiotools_6"))
+ ss, dd = stdr(int(a)), stdr(int(b))
+ xxx = await xxx.edit(
+ f"Downloaded `{file.name}` of `{humanbytes(o_size)}` in `{diff}`.\n\nNow Trimming Audio from `{ss}` to `{dd}`..."
+ )
+ cmd = f'ffmpeg -i "{file.name}" -preset ultrafast -ss {ss} -to {dd} -vn -acodec copy "{out}" -y'
+ await bash(cmd)
+ os.remove(file.name)
+ f_time = time.time()
+ mmmm = await uploader(out, out, f_time, xxx, f"Uploading {out}...")
+ attributes = await set_attributes(out)
+
+ caption = get_string("audiotools_7").format(ss, dd)
+ await e.client.send_file(
+ e.chat_id,
+ mmmm,
+ thumb=ULTConfig.thumb,
+ caption=caption,
+ attributes=attributes,
+ force_document=False,
+ reply_to=e.reply_to_msg_id,
+ )
+ await xxx.delete()
+ else:
+ await e.eor(get_string("audiotools_1"), time=5)
+
+
+@ultroid_cmd(pattern="extractaudio$")
+async def ex_aud(e):
+ reply = await e.get_reply_message()
+ if not (reply and reply.media and mediainfo(reply.media).startswith("video")):
+ return await e.eor(get_string("audiotools_8"))
+ name = reply.file.name or "video.mp4"
+ vfile = reply.media.document
+ msg = await e.eor(get_string("com_1"))
+ c_time = time.time()
+ file = await downloader(
+ f"resources/downloads/{name}",
+ vfile,
+ msg,
+ c_time,
+ f"Downloading {name}...",
+ )
+
+ out_file = f"{file.name}.aac"
+ cmd = f"ffmpeg -i {file.name} -vn -acodec copy {out_file}"
+ o, err = await bash(cmd)
+ os.remove(file.name)
+ attributes = await set_attributes(out_file)
+
+ f_time = time.time()
+ try:
+ fo = await uploader(out_file, out_file, f_time, msg, f"Uploading {out_file}...")
+
+ except FileNotFoundError:
+ return await eor(msg, get_string("audiotools_9"))
+ await e.reply(
+ get_string("audiotools_10"),
+ file=fo,
+ thumb=ULTConfig.thumb,
+ attributes=attributes,
+ )
+ await msg.delete()
diff --git a/plugins/autoban.py b/plugins/autoban.py
new file mode 100644
index 0000000000000000000000000000000000000000..597323213b309398b1f2a8f047f095aa904dc0df
--- /dev/null
+++ b/plugins/autoban.py
@@ -0,0 +1,59 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_autoban")
+
+from telethon import events
+
+from pyUltroid.dB.base import KeyManager
+
+from . import LOGS, asst, ultroid_bot, ultroid_cmd
+
+Keym = KeyManager("DND_CHATS", cast=list)
+
+
+def join_func(e):
+ return e.user_joined and Keym.contains(e.chat_id)
+
+
+async def dnd_func(event):
+ for user in event.users:
+ try:
+ await (await event.client.kick_participant(event.chat_id, user)).delete()
+ except Exception as ex:
+ LOGS.error("Error in DND:")
+ LOGS.exception(ex)
+ await event.delete()
+
+
+@ultroid_cmd(
+ pattern="autokick (on|off)$",
+ admins_only=True,
+ manager=True,
+ require="ban_users",
+ fullsudo=True,
+)
+async def _(event):
+ match = event.pattern_match.group(1)
+ if match == "on":
+ if Keym.contains(event.chat_id):
+ return await event.eor("`Chat already in do not disturb mode.`", time=3)
+ Keym.add(event.chat_id)
+ event.client.add_handler(dnd_func, events.ChatAction(func=join_func))
+ await event.eor("`Do not disturb mode activated for this chat.`", time=3)
+ elif match == "off":
+ if not Keym.contains(event.chat_id):
+ return await event.eor("`Chat is not in do not disturb mode.`", time=3)
+ Keym.remove(event.chat_id)
+ await event.eor("`Do not disturb mode deactivated for this chat.`", time=3)
+
+
+if Keym.get():
+ ultroid_bot.add_handler(dnd_func, events.ChatAction(func=join_func))
+ asst.add_handler(dnd_func, events.ChatAction(func=join_func))
diff --git a/plugins/autopic.py b/plugins/autopic.py
new file mode 100644
index 0000000000000000000000000000000000000000..f6e5127662bc1aaf78bf85ba4bcda347ffc841a3
--- /dev/null
+++ b/plugins/autopic.py
@@ -0,0 +1,84 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+
+import asyncio
+import os
+import random
+from random import shuffle
+
+from telethon.tl.functions.photos import UploadProfilePhotoRequest
+
+from pyUltroid.fns.helper import download_file
+from pyUltroid.fns.tools import get_google_images
+
+from . import LOGS, get_help, get_string, udB, ultroid_bot, ultroid_cmd
+
+__doc__ = get_help("help_autopic")
+
+
+@ultroid_cmd(pattern="autopic( (.*)|$)")
+async def autopic(e):
+ search = e.pattern_match.group(1).strip()
+ if udB.get_key("AUTOPIC") and not search:
+ udB.del_key("AUTOPIC")
+ return await e.eor(get_string("autopic_5"))
+ if not search:
+ return await e.eor(get_string("autopic_1"), time=5)
+ e = await e.eor(get_string("com_1"))
+ gi = googleimagesdownload()
+ args = {
+ "keywords": search,
+ "limit": 50,
+ "format": "jpg",
+ "output_directory": "./resources/downloads/",
+ }
+ try:
+ pth = await gi.download(args)
+ ok = pth[0][search]
+ except Exception as er:
+ LOGS.exception(er)
+ return await e.eor(str(er))
+ if not ok:
+ return await e.eor(get_string("autopic_2").format(search), time=5)
+ await e.eor(get_string("autopic_3").format(search))
+ udB.set_key("AUTOPIC", search)
+ SLEEP_TIME = udB.get_key("SLEEP_TIME") or 1221
+ while True:
+ for lie in ok:
+ if udB.get_key("AUTOPIC") != search:
+ return
+ file = await e.client.upload_file(lie)
+ await e.client(UploadProfilePhotoRequest(file))
+ await asyncio.sleep(SLEEP_TIME)
+ shuffle(ok)
+
+
+if search := udB.get_key("AUTOPIC"):
+ images = {}
+ sleep = udB.get_key("SLEEP_TIME") or 1221
+
+ async def autopic_func():
+ search = udB.get_key("AUTOPIC")
+ if images.get(search) is None:
+ images[search] = await get_google_images(search)
+ if not images.get(search):
+ return
+ img = random.choice(images[search])
+ filee = await download_file(img["original"], "resources/downloads/autopic.jpg")
+ file = await ultroid_bot.upload_file(filee)
+ await ultroid_bot(UploadProfilePhotoRequest(file))
+ os.remove(filee)
+
+ try:
+ from apscheduler.schedulers.asyncio import AsyncIOScheduler
+
+ schedule = AsyncIOScheduler()
+ schedule.add_job(autopic_func, "interval", seconds=sleep)
+ schedule.start()
+ except ModuleNotFoundError as er:
+ LOGS.error(f"autopic: '{er.name}' not installed.")
diff --git a/plugins/beautify.py b/plugins/beautify.py
new file mode 100644
index 0000000000000000000000000000000000000000..efe307d26d6557212168df78c8e333673d802e14
--- /dev/null
+++ b/plugins/beautify.py
@@ -0,0 +1,210 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_beautify")
+
+
+import os
+import random
+
+from telethon.utils import get_display_name
+from urllib.parse import urlencode
+from . import Carbon, ultroid_cmd, get_string, inline_mention, LOGS
+from secrets import token_hex
+
+_colorspath = "resources/colorlist.txt"
+
+if os.path.exists(_colorspath):
+ with open(_colorspath, "r") as f:
+ all_col = f.read().split()
+else:
+ all_col = []
+
+
+@ultroid_cmd(
+ pattern="(rc|c)arbon",
+)
+async def cr_bn(event):
+ xxxx = await event.eor(get_string("com_1"))
+ te = event.pattern_match.group(1)
+ col = random.choice(all_col) if te[0] == "r" else "White"
+ if event.reply_to_msg_id:
+ temp = await event.get_reply_message()
+ if temp.media:
+ b = await event.client.download_media(temp)
+ with open(b) as a:
+ code = a.read()
+ os.remove(b)
+ else:
+ code = temp.message
+ else:
+ try:
+ code = event.text.split(" ", maxsplit=1)[1]
+ except IndexError:
+ return await xxxx.eor(get_string("carbon_2"))
+ xx = await Carbon(code=code, file_name="ultroid_carbon", backgroundColor=col)
+ if isinstance(xx, dict):
+ await xxxx.edit(f"`{xx}`")
+ return
+ await xxxx.delete()
+ await event.reply(
+ f"Carbonised by {inline_mention(event.sender)}",
+ file=xx,
+ )
+
+
+@ultroid_cmd(
+ pattern="ccarbon( (.*)|$)",
+)
+async def crbn(event):
+ match = event.pattern_match.group(1).strip()
+ if not match:
+ return await event.eor(get_string("carbon_3"))
+ msg = await event.eor(get_string("com_1"))
+ if event.reply_to_msg_id:
+ temp = await event.get_reply_message()
+ if temp.media:
+ b = await event.client.download_media(temp)
+ with open(b) as a:
+ code = a.read()
+ os.remove(b)
+ else:
+ code = temp.message
+ else:
+ try:
+ match = match.split(" ", maxsplit=1)
+ code = match[1]
+ match = match[0]
+ except IndexError:
+ return await msg.eor(get_string("carbon_2"))
+ xx = await Carbon(code=code, backgroundColor=match)
+ await msg.delete()
+ await event.reply(
+ f"Carbonised by {inline_mention(event.sender)}",
+ file=xx,
+ )
+
+
+RaySoTheme = [
+ "meadow",
+ "breeze",
+ "raindrop",
+ "candy",
+ "crimson",
+ "falcon",
+ "sunset",
+ "noir",
+ "midnight",
+ "bitmap",
+ "ice",
+ "sand",
+ "forest",
+ "mono"
+]
+
+
+@ultroid_cmd(pattern="rayso")
+async def pass_on(ult):
+ try:
+ from playwright.async_api import async_playwright
+ except ImportError:
+ await ult.eor("`playwright` is not installed!\nPlease install it to use this command..")
+ return
+
+ proc = await ult.eor(get_string("com_1"))
+ spli = ult.text.split()
+ theme, dark, title, text = None, True, get_display_name(ult.chat), None
+
+ if len(spli) > 2:
+ if spli[1] in RaySoTheme:
+ theme = spli[1]
+ dark = spli[2].lower().strip() in ["true", "t"]
+ elif len(spli) > 1:
+ if spli[1] in RaySoTheme:
+ theme = spli[1]
+ elif spli[1] == "list":
+ text = "**List of Rayso Themes:**\n" + "\n".join([f"- `{th_}`" for th_ in RaySoTheme])
+ await proc.eor(text)
+ return
+ else:
+ try:
+ text = ult.text.split(maxsplit=1)[1]
+ except IndexError:
+ pass
+
+ if not theme or theme not in RaySoTheme:
+ theme = random.choice(RaySoTheme)
+
+ if ult.is_reply:
+ try:
+ msg = await ult.get_reply_message()
+ text = msg.message
+ title = get_display_name(msg.sender)
+ except Exception as sam:
+ ErrInfo(sam)
+
+ if not text:
+ await proc.eor("No text to beautify!")
+ return
+
+ cleaned_text = "\n".join([line.strip() for line in text.splitlines()])
+
+ name = token_hex(8) + ".png"
+ data = {"darkMode": dark, "theme": theme, "title": title}
+ url = f"https://ray.so/#{urlencode(data)}"
+
+ async with async_playwright() as play:
+ try:
+# browser = await play.chromium.launch(headless=False) # Set to False for debugging
+ browser = await play.chromium.launch(headless=True, args=["--disable-crash-reporter"])
+ page = await browser.new_page()
+ await page.goto(url, timeout=60000) # Increase timeout
+ await page.wait_for_load_state("networkidle")
+
+ try:
+ await page.wait_for_selector("div[class*='Editor_editor__']", timeout=60000)
+ editor = await page.query_selector("div[class*='Editor_editor__']")
+ await editor.focus()
+ await editor.click()
+
+ for line in cleaned_text.split("\n"):
+ await page.keyboard.type(line)
+ await page.keyboard.press("Enter")
+
+ await page.evaluate("""() => {
+ const button = document.querySelector('button[aria-label="Export as PNG"]');
+ button.click();
+ }""")
+
+ async with page.expect_download() as download_info:
+ download = await download_info.value
+ await download.save_as(name)
+
+ except playwright._impl._errors.TimeoutError:
+ LOGS.info("Timeout error: Selector not found within 60 seconds.")
+ await proc.eor("Failed to find the editor within 60 seconds.")
+ return
+
+ except Exception as e:
+ LOGS.info(f"Error occurred during playwright operation: {e}")
+ await proc.eor("An error occurred during the operation.")
+ return
+
+ finally:
+ if os.path.exists(name):
+ try:
+ await ult.reply(file=name)
+ await proc.try_delete()
+ os.remove(name)
+ except Exception as e:
+ LOGS.info(f"Error occurred while replying with the file: {e}")
+ await proc.eor("Failed to send the file.")
+ else:
+ LOGS.info(f"Error: File {name} not found or inaccessible.")
+ await proc.eor("Failed to save the file.")
diff --git a/plugins/blacklist.py b/plugins/blacklist.py
new file mode 100644
index 0000000000000000000000000000000000000000..78f2d42afe65f3cf377a7b28654333fa806446ba
--- /dev/null
+++ b/plugins/blacklist.py
@@ -0,0 +1,69 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_blacklist")
+
+
+from pyUltroid.dB.blacklist_db import (
+ add_blacklist,
+ get_blacklist,
+ list_blacklist,
+ rem_blacklist,
+)
+
+from . import events, get_string, udB, ultroid_bot, ultroid_cmd
+
+
+@ultroid_cmd(pattern="blacklist( (.*)|$)", admins_only=True)
+async def af(e):
+ wrd = e.pattern_match.group(1).strip()
+ chat = e.chat_id
+ if not (wrd):
+ return await e.eor(get_string("blk_1"), time=5)
+ wrd = e.text[11:]
+ heh = wrd.split(" ")
+ for z in heh:
+ add_blacklist(int(chat), z.lower())
+ ultroid_bot.add_handler(blacklist, events.NewMessage(incoming=True))
+ await e.eor(get_string("blk_2").format(wrd))
+
+
+@ultroid_cmd(pattern="remblacklist( (.*)|$)", admins_only=True)
+async def rf(e):
+ wrd = e.pattern_match.group(1).strip()
+ chat = e.chat_id
+ if not wrd:
+ return await e.eor(get_string("blk_3"), time=5)
+ wrd = e.text[14:]
+ heh = wrd.split(" ")
+ for z in heh:
+ rem_blacklist(int(chat), z.lower())
+ await e.eor(get_string("blk_4").format(wrd))
+
+
+@ultroid_cmd(pattern="listblacklist$", admins_only=True)
+async def lsnote(e):
+ if x := list_blacklist(e.chat_id):
+ sd = get_string("blk_5")
+ return await e.eor(sd + x)
+ await e.eor(get_string("blk_6"))
+
+
+async def blacklist(e):
+ if x := get_blacklist(e.chat_id):
+ text = e.text.lower().split()
+ if any((z in text) for z in x):
+ try:
+ await e.delete()
+ except BaseException:
+ pass
+
+
+if udB.get_key("BLACKLIST_DB"):
+ ultroid_bot.add_handler(blacklist, events.NewMessage(incoming=True))
diff --git a/plugins/bot.py b/plugins/bot.py
new file mode 100644
index 0000000000000000000000000000000000000000..2209c64b66ee550c74bcf0c991428b02b8e9eb02
--- /dev/null
+++ b/plugins/bot.py
@@ -0,0 +1,358 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_bot")
+
+import os
+import sys
+import time
+from platform import python_version as pyver
+from random import choice
+
+from telethon import __version__
+from telethon.errors.rpcerrorlist import (
+ BotMethodInvalidError,
+ ChatSendMediaForbiddenError,
+)
+
+from pyUltroid.version import __version__ as UltVer
+
+from . import HOSTED_ON, LOGS
+
+try:
+ from git import Repo
+except ImportError:
+ LOGS.error("bot: 'gitpython' module not found!")
+ Repo = None
+
+from telethon.utils import resolve_bot_file_id
+
+from . import (
+ ATRA_COL,
+ LOGS,
+ OWNER_NAME,
+ ULTROID_IMAGES,
+ Button,
+ Carbon,
+ Telegraph,
+ Var,
+ allcmds,
+ asst,
+ bash,
+ call_back,
+ callback,
+ def_logs,
+ eor,
+ get_string,
+ heroku_logs,
+ in_pattern,
+ inline_pic,
+ restart,
+ shutdown,
+ start_time,
+ time_formatter,
+ udB,
+ ultroid_cmd,
+ ultroid_version,
+ updater,
+)
+
+
+def ULTPIC():
+ return inline_pic() or choice(ULTROID_IMAGES)
+
+
+buttons = [
+ [
+ Button.url(get_string("bot_3"), "https://github.com/TeamUltroid/Ultroid"),
+ Button.url(get_string("bot_4"), "t.me/UltroidSupportChat"),
+ ]
+]
+
+# Will move to strings
+alive_txt = """
+The Ultroid Userbot
+
+ ◍ Version - {}
+ ◍ Py-Ultroid - {}
+ ◍ Telethon - {}
+"""
+
+in_alive = "{}\n\n🌀 Ultroid Version -> {}
\n🌀 PyUltroid -> {}
\n🌀 Python -> {}
\n🌀 Uptime -> {}
\n🌀 Branch ->[ {} ]\n\n• Join @TeamUltroid"
+
+
+@callback("alive")
+async def alive(event):
+ text = alive_txt.format(ultroid_version, UltVer, __version__)
+ await event.answer(text, alert=True)
+
+
+@ultroid_cmd(
+ pattern="alive( (.*)|$)",
+)
+async def lol(ult):
+ match = ult.pattern_match.group(1).strip()
+ inline = None
+ if match in ["inline", "i"]:
+ try:
+ res = await ult.client.inline_query(asst.me.username, "alive")
+ return await res[0].click(ult.chat_id)
+ except BotMethodInvalidError:
+ pass
+ except BaseException as er:
+ LOGS.exception(er)
+ inline = True
+ pic = udB.get_key("ALIVE_PIC")
+ if isinstance(pic, list):
+ pic = choice(pic)
+ uptime = time_formatter((time.time() - start_time) * 1000)
+ header = udB.get_key("ALIVE_TEXT") or get_string("bot_1")
+# y = Repo().active_branch
+ y = "main"
+# xx = Repo().remotes[0].config_reader.get("url")
+ xx = "https://github.com/ufoptg/UltroidBackup.git"
+ rep = xx.replace(".git", f"/tree/{y}")
+ kk = f" `[{y}]({rep})` "
+ if inline:
+ kk = f"{y}"
+ parse = "html"
+ als = in_alive.format(
+ header,
+ f"{ultroid_version} [{HOSTED_ON}]",
+ UltVer,
+ pyver(),
+ uptime,
+ kk,
+ )
+
+ if _e := udB.get_key("ALIVE_EMOJI"):
+ als = als.replace("🌀", _e)
+ else:
+ parse = "md"
+ als = (get_string("alive_1")).format(
+ header,
+ OWNER_NAME,
+ f"{ultroid_version} [{HOSTED_ON}]",
+ UltVer,
+ uptime,
+ pyver(),
+ __version__,
+ kk,
+ )
+
+ if a := udB.get_key("ALIVE_EMOJI"):
+ als = als.replace("✵", a)
+ if pic:
+ try:
+ await ult.reply(
+ als,
+ file=pic,
+ parse_mode=parse,
+ link_preview=False,
+ buttons=buttons if inline else None,
+ )
+ return await ult.try_delete()
+ except ChatSendMediaForbiddenError:
+ pass
+ except BaseException as er:
+ LOGS.exception(er)
+ try:
+ await ult.reply(file=pic)
+ await ult.reply(
+ als,
+ parse_mode=parse,
+ buttons=buttons if inline else None,
+ link_preview=False,
+ )
+ return await ult.try_delete()
+ except BaseException as er:
+ LOGS.exception(er)
+ await eor(
+ ult,
+ als,
+ parse_mode=parse,
+ link_preview=False,
+ buttons=buttons if inline else None,
+ )
+
+
+@ultroid_cmd(pattern="ping$", chats=[], type=["official", "assistant"])
+async def _(event):
+ start = time.time()
+ x = await event.eor("Pong !")
+ end = round((time.time() - start) * 1000)
+ uptime = time_formatter((time.time() - start_time) * 1000)
+ await x.edit(get_string("ping").format(end, uptime))
+
+
+@ultroid_cmd(
+ pattern="cmds$",
+)
+async def cmds(event):
+ await allcmds(event, Telegraph)
+
+
+heroku_api = Var.HEROKU_API
+
+
+@ultroid_cmd(
+ pattern="restart$",
+ fullsudo=True,
+)
+async def restartbt(ult):
+ ok = await ult.eor(get_string("bot_5"))
+ call_back()
+ who = "bot" if ult.client._bot else "user"
+ udB.set_key("_RESTART", f"{who}_{ult.chat_id}_{ok.id}")
+ if heroku_api:
+ return await restart(ok)
+ await bash("git pull && pip3 install -r requirements.txt")
+ if len(sys.argv) > 1:
+ os.execl(sys.executable, sys.executable, "main.py")
+ else:
+ os.execl(sys.executable, sys.executable, "-m", "pyUltroid")
+
+
+@ultroid_cmd(
+ pattern="shutdown$",
+ fullsudo=True,
+)
+async def shutdownbot(ult):
+ await shutdown(ult)
+
+
+@ultroid_cmd(
+ pattern="logs( (.*)|$)",
+ chats=[],
+)
+async def _(event):
+ opt = event.pattern_match.group(1).strip()
+ file = f"ultroid{sys.argv[-1]}.log" if len(sys.argv) > 1 else "ultroid.log"
+ if opt == "heroku":
+ await heroku_logs(event)
+ elif opt == "carbon" and Carbon:
+ event = await event.eor(get_string("com_1"))
+ with open(file, "r") as f:
+ code = f.read()[-2500:]
+ file = await Carbon(
+ file_name="ultroid-logs",
+ code=code,
+ backgroundColor=choice(ATRA_COL),
+ )
+ if isinstance(file, dict):
+ await event.eor(f"`{file}`")
+ return
+ await event.reply("**Ultroid Logs.**", file=file)
+ elif opt == "open":
+ with open("ultroid.log", "r") as f:
+ file = f.read()[-4000:]
+ return await event.eor(f"`{file}`")
+ else:
+ await def_logs(event, file)
+ await event.try_delete()
+
+
+@in_pattern("alive", owner=True)
+async def inline_alive(ult):
+ pic = udB.get_key("ALIVE_PIC")
+ if isinstance(pic, list):
+ pic = choice(pic)
+ uptime = time_formatter((time.time() - start_time) * 1000)
+ header = udB.get_key("ALIVE_TEXT") or get_string("bot_1")
+ y = Repo().active_branch
+ xx = Repo().remotes[0].config_reader.get("url")
+ rep = xx.replace(".git", f"/tree/{y}")
+ kk = f"{y}"
+ als = in_alive.format(
+ header, f"{ultroid_version} [{HOSTED_ON}]", UltVer, pyver(), uptime, kk
+ )
+
+ if _e := udB.get_key("ALIVE_EMOJI"):
+ als = als.replace("🌀", _e)
+ builder = ult.builder
+ if pic:
+ try:
+ if ".jpg" in pic:
+ results = [
+ await builder.photo(
+ pic, text=als, parse_mode="html", buttons=buttons
+ )
+ ]
+ else:
+ if _pic := resolve_bot_file_id(pic):
+ pic = _pic
+ buttons.insert(
+ 0, [Button.inline(get_string("bot_2"), data="alive")]
+ )
+ results = [
+ await builder.document(
+ pic,
+ title="Inline Alive",
+ description="@TeamUltroid",
+ parse_mode="html",
+ buttons=buttons,
+ )
+ ]
+ return await ult.answer(results)
+ except BaseException as er:
+ LOGS.exception(er)
+ result = [
+ await builder.article(
+ "Alive", text=als, parse_mode="html", link_preview=False, buttons=buttons
+ )
+ ]
+ await ult.answer(result)
+
+
+@ultroid_cmd(pattern="update( (.*)|$)")
+async def _(e):
+ xx = await e.eor(get_string("upd_1"))
+ if e.pattern_match.group(1).strip() and (
+ "fast" in e.pattern_match.group(1).strip()
+ or "soft" in e.pattern_match.group(1).strip()
+ ):
+ await bash("git pull -f && pip3 install -r requirements.txt")
+ call_back()
+ await xx.edit(get_string("upd_7"))
+ os.execl(sys.executable, "python3", "-m", "pyUltroid")
+ # return
+ m = await updater()
+ branch = (Repo.init()).active_branch
+ if m:
+ x = await asst.send_file(
+ udB.get_key("LOG_CHANNEL"),
+ ULTPIC(),
+ caption="• **Update Available** •",
+ force_document=False,
+ buttons=Button.inline("Changelogs", data="changes"),
+ )
+ Link = x.message_link
+ await xx.edit(
+ f'[ChangeLogs]',
+ parse_mode="html",
+ link_preview=False,
+ )
+ else:
+ await xx.edit(
+ f'Your BOT is
up-to-date with
[{branch}]',
+ parse_mode="html",
+ link_preview=False,
+ )
+
+
+@callback("updtavail", owner=True)
+async def updava(event):
+ await event.delete()
+ await asst.send_file(
+ udB.get_key("LOG_CHANNEL"),
+ ULTPIC(),
+ caption="• **Update Available** •",
+ force_document=False,
+ buttons=Button.inline("Changelogs", data="changes"),
+ )
diff --git a/plugins/broadcast.py b/plugins/broadcast.py
new file mode 100644
index 0000000000000000000000000000000000000000..f8aedf2f086d04c9a54d45d90b9d031af2ad66ae
--- /dev/null
+++ b/plugins/broadcast.py
@@ -0,0 +1,216 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+
+from . import get_help
+
+__doc__ = get_help("help_broadcast")
+
+import asyncio
+import io
+
+from telethon.utils import get_display_name
+
+from pyUltroid.dB.base import KeyManager
+
+from . import HNDLR, LOGS, eor, get_string, udB, ultroid_bot, ultroid_cmd
+
+KeyM = KeyManager("BROADCAST", cast=list)
+
+
+@ultroid_cmd(
+ pattern="addch( (.*)|$)",
+ allow_sudo=False,
+)
+async def broadcast_adder(event):
+ msgg = event.pattern_match.group(1).strip()
+ x = await event.eor(get_string("bd_1"))
+ if msgg == "all":
+ await x.edit(get_string("bd_2"))
+ chats = [
+ e.entity
+ for e in await event.client.get_dialogs()
+ if (e.is_group or e.is_channel)
+ ]
+ new = 0
+ for i in chats:
+ try:
+ if (
+ i.broadcast
+ and (i.creator or i.admin_rights)
+ and not KeyM.contains(i.id)
+ ):
+ new += 1
+ cid = f"-100{i.id}"
+ KeyM.add(int(cid))
+ except Exception as Ex:
+ LOGS.exception(Ex)
+ await x.edit(get_string("bd_3").format(KeyM.count(), new))
+ return
+ if event.reply_to_msg_id:
+ previous_message = await event.get_reply_message()
+ raw_text = previous_message.text
+ lines = raw_text.split("\n")
+ length = len(lines)
+ for line_number in range(1, length - 2):
+ channel_id = lines[line_number][4:-1]
+ if not KeyM.contains(channel_id):
+ KeyM.add(channel_id)
+ await x.edit(get_string("bd_4"))
+ await asyncio.sleep(3)
+ await event.delete()
+ return
+ chat_id = event.chat_id
+ if chat_id == udB.get_key("LOG_CHANNEL"):
+ return
+ if KeyM.contains(chat_id):
+ await x.edit(get_string("bd_6"))
+ elif xx := KeyM.add(chat_id):
+ await x.edit(get_string("bd_5"))
+ else:
+ await x.edit(get_string("sf_8"))
+ await asyncio.sleep(3)
+ await x.delete()
+
+
+@ultroid_cmd(
+ pattern="remch( (.*)|$)",
+ allow_sudo=False,
+)
+async def broadcast_remover(event):
+ chat_id = event.pattern_match.group(1).strip() or event.chat_id
+ x = await event.eor(get_string("com_1"))
+ if chat_id == "all":
+ await x.edit(get_string("bd_8"))
+ udB.del_key("BROADCAST")
+ await x.edit("Database cleared.")
+ return
+ if KeyM.contains(chat_id):
+ KeyM.remove(chat_id)
+ await x.edit(get_string("bd_7"))
+ else:
+ await x.edit(get_string("bd_9"))
+ await asyncio.sleep(3)
+ await x.delete()
+
+
+@ultroid_cmd(
+ pattern="listchannels$",
+)
+async def list_all(event):
+ x = await event.eor(get_string("com_1"))
+ channels = KeyM.get()
+ num = KeyM.count()
+ if not channels:
+ return await eor(x, "No chats were added.", time=5)
+ msg = "Channels in database:\n"
+ for channel in channels:
+ name = ""
+ try:
+ name = get_display_name(await event.client.get_entity(channel))
+ except ValueError:
+ name = ""
+ msg += f"=> **{name}** [`{channel}`]\n"
+ msg += f"\nTotal {num} channels."
+ if len(msg) > 4096:
+ MSG = msg.replace("*", "").replace("`", "")
+ with io.BytesIO(str.encode(MSG)) as out_file:
+ out_file.name = "channels.txt"
+ await event.reply(
+ "Channels in Database",
+ file=out_file,
+ force_document=True,
+ allow_cache=False,
+ )
+ await x.delete()
+ else:
+ await x.edit(msg)
+
+
+@ultroid_cmd(
+ pattern="forward$",
+ allow_sudo=False,
+)
+async def forw(event):
+ if not event.is_reply:
+ return await event.eor(get_string("ex_1"))
+ ultroid_bot = event.client
+ channels = KeyM.get()
+ x = await event.eor("Sending...")
+ if not channels:
+ return await x.edit(f"Please add channels by using `{HNDLR}add` in them.")
+ error_count = 0
+ sent_count = 0
+ previous_message = await event.get_reply_message()
+ error_count = 0
+ for channel in channels:
+ try:
+ await ultroid_bot.forward_messages(channel, previous_message)
+ sent_count += 1
+ await x.edit(
+ f"Sent : {sent_count}\nError : {error_count}\nTotal : {len(channels)}",
+ )
+ except Exception:
+ try:
+ await ultroid_bot.send_message(
+ udB.get_key("LOG_CHANNEL"),
+ f"Error in sending at {channel}.",
+ )
+ except Exception as Em:
+ LOGS.info(Em)
+ error_count += 1
+ await x.edit(
+ f"Sent : {sent_count}\nError : {error_count}\nTotal : {len(channels)}",
+ )
+ await x.edit(f"{sent_count} messages sent with {error_count} errors.")
+ if error_count > 0:
+ await ultroid_bot.send_message(
+ udB.get_key("LOG_CHANNEL"), f"{error_count} Errors"
+ )
+
+
+@ultroid_cmd(
+ pattern="broadcast( (.*)|$)",
+ allow_sudo=False,
+)
+async def sending(event):
+ x = await event.eor(get_string("com_1"))
+ if not event.is_reply:
+ return await x.edit(get_string("ex_1"))
+ channels = KeyM.get()
+ if not channels:
+ return await x.edit(f"Please add channels by using `{HNDLR}add` in them.")
+ await x.edit("Sending....")
+ if event.reply_to_msg_id:
+ previous_message = await event.get_reply_message()
+ if previous_message.poll:
+ return await x.edit(f"Reply `{HNDLR}forward` for polls.")
+ if previous_message:
+ error_count = 0
+ sent_count = 0
+ for channel in channels:
+ try:
+ await ultroid_bot.send_message(channel, previous_message)
+ sent_count += 1
+ await x.edit(
+ f"Sent : {sent_count}\nError : {error_count}\nTotal : {len(channels)}",
+ )
+ except Exception as error:
+ await ultroid_bot.send_message(
+ udB.get_key("LOG_CHANNEL"),
+ f"Error in sending at {channel}.\n\n{error}",
+ )
+ error_count += 1
+ await x.edit(
+ f"Sent : {sent_count}\nError : {error_count}\nTotal : {len(channels)}",
+ )
+ await x.edit(f"{sent_count} messages sent with {error_count} errors.")
+ if error_count > 0:
+ await ultroid_bot.send_message(
+ udB.get_key("LOG_CHANNEL"),
+ f"{error_count} Errors",
+ )
diff --git a/plugins/button.py b/plugins/button.py
new file mode 100644
index 0000000000000000000000000000000000000000..b3d616d709be1a04ede2c6996d393bf12ac27f56
--- /dev/null
+++ b/plugins/button.py
@@ -0,0 +1,56 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_button")
+
+import os
+
+from telegraph import upload_file as uf
+from telethon.utils import pack_bot_file_id
+
+from pyUltroid.fns.tools import create_tl_btn, get_msg_button
+
+from . import HNDLR, get_string, mediainfo, ultroid_cmd
+from ._inline import something
+
+
+@ultroid_cmd(pattern="button")
+async def butt(event):
+ media, wut, text = None, None, None
+ if event.reply_to:
+ wt = await event.get_reply_message()
+ if wt.text:
+ text = wt.text
+ if wt.media:
+ wut = mediainfo(wt.media)
+ if wut and wut.startswith(("pic", "gif")):
+ dl = await wt.download_media()
+ variable = uf(dl)
+ media = f"https://graph.org{variable[0]}"
+ elif wut == "video":
+ if wt.media.document.size > 8 * 1000 * 1000:
+ return await event.eor(get_string("com_4"), time=5)
+ dl = await wt.download_media()
+ variable = uf(dl)
+ os.remove(dl)
+ media = f"https://graph.org{variable[0]}"
+ else:
+ media = pack_bot_file_id(wt.media)
+ try:
+ text = event.text.split(maxsplit=1)[1]
+ except IndexError:
+ if not text:
+ return await event.eor(
+ f"**Please give some text in correct format.**\n\n`{HNDLR}help button`",
+ )
+ text, buttons = get_msg_button(text)
+ if buttons:
+ buttons = create_tl_btn(buttons)
+ await something(event, text, media, buttons)
+ await event.delete()
diff --git a/plugins/calculator.py b/plugins/calculator.py
new file mode 100644
index 0000000000000000000000000000000000000000..28f2bae144d25287460e4a08daa452c6acba2f9f
--- /dev/null
+++ b/plugins/calculator.py
@@ -0,0 +1,153 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+
+from . import get_help
+
+__doc__ = get_help("help_calculator")
+
+import re
+
+from . import Button, asst, callback, get_string, in_pattern, udB, ultroid_cmd
+
+CALC = {}
+
+m = [
+ "AC",
+ "C",
+ "⌫",
+ "%",
+ "7",
+ "8",
+ "9",
+ "+",
+ "4",
+ "5",
+ "6",
+ "-",
+ "1",
+ "2",
+ "3",
+ "x",
+ "00",
+ "0",
+ ".",
+ "÷",
+]
+tultd = [Button.inline(f"{x}", data=f"calc{x}") for x in m]
+lst = list(zip(tultd[::4], tultd[1::4], tultd[2::4], tultd[3::4]))
+lst.append([Button.inline("=", data="calc=")])
+
+
+@ultroid_cmd(pattern="calc")
+async def icalc(e):
+ udB.del_key("calc")
+ if e.client._bot:
+ return await e.reply(get_string("calc_1"), buttons=lst)
+ results = await e.client.inline_query(asst.me.username, "calc")
+ await results[0].click(e.chat_id, silent=True, hide_via=True)
+ await e.delete()
+
+
+@in_pattern("calc", owner=True)
+async def _(e):
+ calc = e.builder.article("Calc", text=get_string("calc_1"), buttons=lst)
+ await e.answer([calc])
+
+
+@callback(re.compile("calc(.*)"), owner=True)
+async def _(e):
+ x = (e.data_match.group(1)).decode()
+ user = e.query.user_id
+ get = None
+ if x == "AC":
+ if CALC.get(user):
+ CALC.pop(user)
+ await e.edit(
+ get_string("calc_1"),
+ buttons=[Button.inline(get_string("calc_2"), data="recalc")],
+ )
+ elif x == "C":
+ if CALC.get(user):
+ CALC.pop(user)
+ await e.answer("cleared")
+ elif x == "⌫":
+ if CALC.get(user):
+ get = CALC[user]
+ if get:
+ CALC.update({user: get[:-1]})
+ await e.answer(str(get[:-1]))
+ elif x == "%":
+ if CALC.get(user):
+ get = CALC[user]
+ if get:
+ CALC.update({user: f"{get}/100"})
+ await e.answer(str(f"{get}/100"))
+ elif x == "÷":
+ if CALC.get(user):
+ get = CALC[user]
+ if get:
+ CALC.update({user: f"{get}/"})
+ await e.answer(str(f"{get}/"))
+ elif x == "x":
+ if CALC.get(user):
+ get = CALC[user]
+ if get:
+ CALC.update({user: f"{get}*"})
+ await e.answer(str(f"{get}*"))
+ elif x == "=":
+ if CALC.get(user):
+ get = CALC[user]
+ if get:
+ if get.endswith(("*", ".", "/", "-", "+")):
+ get = get[:-1]
+ out = eval(get)
+ try:
+ num = float(out)
+ await e.answer(f"Answer : {num}", cache_time=0, alert=True)
+ except BaseException:
+ CALC.pop(user)
+ await e.answer(get_string("sf_8"), cache_time=0, alert=True)
+ await e.answer("None")
+ else:
+ if CALC.get(user):
+ get = CALC[user]
+ if get:
+ CALC.update({user: get + x})
+ return await e.answer(str(get + x))
+ CALC.update({user: x})
+ await e.answer(str(x))
+
+
+@callback("recalc", owner=True)
+async def _(e):
+ m = [
+ "AC",
+ "C",
+ "⌫",
+ "%",
+ "7",
+ "8",
+ "9",
+ "+",
+ "4",
+ "5",
+ "6",
+ "-",
+ "1",
+ "2",
+ "3",
+ "x",
+ "00",
+ "0",
+ ".",
+ "÷",
+ ]
+ tultd = [Button.inline(f"{x}", data=f"calc{x}") for x in m]
+ lst = list(zip(tultd[::4], tultd[1::4], tultd[2::4], tultd[3::4]))
+ lst.append([Button.inline("=", data="calc=")])
+ await e.edit(get_string("calc_1"), buttons=lst)
diff --git a/plugins/channelhacks.py b/plugins/channelhacks.py
new file mode 100644
index 0000000000000000000000000000000000000000..d333249a0fc0a82ec5cd8f37ec3014b25c21bcb6
--- /dev/null
+++ b/plugins/channelhacks.py
@@ -0,0 +1,224 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+from . import get_help
+
+__doc__ = get_help("help_channelhacks")
+
+
+import asyncio
+import io
+
+from telethon.errors.rpcerrorlist import FloodWaitError
+from telethon.utils import get_display_name, get_peer_id
+
+from pyUltroid.dB.base import KeyManager
+
+from . import LOGS, asst, eor, events, get_string, udB, ultroid_bot, ultroid_cmd
+
+ERROR = {}
+SourceM = KeyManager("CH_SOURCE", cast=list)
+DestiM = KeyManager("CH_DESTINATIONS", cast=list)
+
+
+async def autopost_func(e):
+ if not udB.get_key("AUTOPOST"):
+ return
+ x = SourceM.get()
+ th = await e.get_chat()
+ if get_peer_id(th) not in x:
+ return
+ y = DestiM.get()
+ for ys in y:
+ try:
+ await e.client.send_message(int(ys), e.message)
+ except Exception as ex:
+ try:
+ ERROR[str(ex)]
+ except KeyError:
+ ERROR.update({str(ex): ex})
+ Error = f"**Error on AUTOPOST**\n\n`{ex}`"
+ await asst.send_message(udB.get_key("LOG_CHANNEL"), Error)
+
+
+@ultroid_cmd(pattern="shift (.*)")
+async def _(e):
+ x = e.pattern_match.group(1).strip()
+ z = await e.eor(get_string("com_1"))
+ a, b = x.split("|")
+ try:
+ c = await e.client.parse_id(a)
+ except Exception:
+ await z.edit(get_string("cha_1"))
+ return
+ try:
+ d = await e.client.parse_id(b)
+ except Exception as er:
+ LOGS.exception(er)
+ await z.edit(get_string("cha_1"))
+ return
+ async for msg in e.client.iter_messages(int(c), reverse=True):
+ try:
+ await asyncio.sleep(2)
+ await e.client.send_message(int(d), msg)
+ except FloodWaitError as er:
+ await asyncio.sleep(er.seconds + 5)
+ await e.client.send_message(int(d), msg)
+ except BaseException as er:
+ LOGS.exception(er)
+ await z.edit("Done")
+
+
+@ultroid_cmd(pattern="asource (.*)")
+async def source(e):
+ if x := e.pattern_match.group(1).strip():
+ try:
+ y = await e.client.parse_id(x)
+ except Exception as er:
+ LOGS.exception(er)
+ return
+ else:
+ y = e.chat_id
+ if not SourceM.contains(y):
+ SourceM.add(y)
+ await e.eor(get_string("cha_2"))
+ ultroid_bot.add_handler(autopost_func, events.NewMessage())
+ else:
+ await e.eor(get_string("cha_3"))
+
+
+@ultroid_cmd(pattern="dsource( (.*)|$)")
+async def dd(event):
+ chat_id = event.pattern_match.group(1).strip()
+ x = await event.eor(get_string("com_1"))
+ if chat_id == "all":
+ await x.edit(get_string("bd_8"))
+ udB.del_key("CH_SOURCE")
+ await x.edit(get_string("cha_4"))
+ return
+ if chat_id:
+ try:
+ y = await event.client.parse_id(chat_id)
+ except Exception as er:
+ LOGS.exception(er)
+ return
+ else:
+ y = event.chat_id
+ if SourceM.contains(y):
+ SourceM.remove(y)
+ await eor(x, get_string("cha_5"), time=5)
+ else:
+ await eor(x, "Source channel is already removed from database. ", time=3)
+
+
+@ultroid_cmd(pattern="listsource")
+async def list_all(event):
+ x = await event.eor(get_string("com_1"))
+ num = SourceM.count()
+ if not num:
+ return await eor(x, "No chats were added.", time=5)
+ msg = get_string("cha_8")
+ channels = SourceM.get()
+ for channel in channels:
+ name = ""
+ try:
+ name = get_display_name(await event.client.get_entity(int(channel)))
+ except BaseException:
+ name = ""
+ msg += f"\n=> **{name}** [`{channel}`]"
+ msg += f"\nTotal {num} channels."
+ if len(msg) > 4096:
+ MSG = msg.replace("*", "").replace("`", "")
+ with io.BytesIO(str.encode(MSG)) as out_file:
+ out_file.name = "channels.txt"
+ await event.reply(
+ "Channels in database",
+ file=out_file,
+ force_document=True,
+ allow_cache=False,
+ )
+ await x.delete()
+ else:
+ await x.edit(msg)
+
+
+@ultroid_cmd(pattern="adest (.*)")
+async def destination(e):
+ if x := e.pattern_match.group(1).strip():
+ try:
+ y = await e.client.parse_id(x)
+ except Exception as er:
+ LOGS.exception(er)
+ return
+ else:
+ y = e.chat_id
+ if not DestiM.contains(y):
+ DestiM.add(y)
+ await e.eor("Destination added succesfully")
+ else:
+ await e.eor("Destination channel already added")
+
+
+@ultroid_cmd(pattern="ddest( (.*)|$)")
+async def dd(event):
+ chat_id = event.pattern_match.group(1).strip()
+ x = await event.eor(get_string("com_1"))
+ if chat_id == "all":
+ await x.edit(get_string("bd_8"))
+ udB.del_key("CH_DESTINATION")
+ await x.edit("Destinations database cleared.")
+ return
+ if chat_id:
+ try:
+ y = await event.client.parse_id(chat_id)
+ except Exception as er:
+ LOGS.exception(er)
+ return
+ else:
+ y = event.chat_id
+ if DestiM.contains(y):
+ DestiM.remove(y)
+ await eor(x, "Destination removed from database")
+ else:
+ await eor(x, "Destination channel is already removed from database. ", time=5)
+
+
+@ultroid_cmd(pattern="listdest")
+async def list_all(event):
+ ultroid_bot = event.client
+ x = await event.eor(get_string("com_1"))
+ channels = DestiM.get()
+ num = len(channels)
+ if not num:
+ return await eor(x, "No chats were added.", time=5)
+ msg = get_string("cha_7")
+ for channel in channels:
+ name = ""
+ try:
+ name = get_display_name(await ultroid_bot.get_entity(int(channel)))
+ except BaseException:
+ name = ""
+ msg += f"\n=> **{name}** [`{channel}`]"
+ msg += f"\nTotal {num} channels."
+ if len(msg) > 4096:
+ MSG = msg.replace("*", "").replace("`", "")
+ with io.BytesIO(str.encode(MSG)) as out_file:
+ out_file.name = "channels.txt"
+ await ultroid_bot.send_file(
+ event.chat_id,
+ out_file,
+ force_document=True,
+ allow_cache=False,
+ caption="Destination channels in database",
+ reply_to=event,
+ )
+ await x.delete()
+ else:
+ await x.edit(msg)
+
+
+if udB.get_key("AUTOPOST"):
+ ultroid_bot.add_handler(autopost_func, events.NewMessage())
diff --git a/plugins/chatbot.py b/plugins/chatbot.py
new file mode 100644
index 0000000000000000000000000000000000000000..0dfcec7359f0976288e4ef885567bd21180e90ba
--- /dev/null
+++ b/plugins/chatbot.py
@@ -0,0 +1,174 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2024 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_chatbot")
+
+
+from pyUltroid.fns.tools import get_chatbot_reply, get_oracle_reply
+
+from . import LOGS, eod, get_string, inline_mention, udB, ultroid_bot, ultroid_cmd
+
+try:
+ mongouri = udB.get_key("MONGO_URI")
+except AttributeError:
+ if udB.get_key("MONGO_URI"):
+ mongouri = udB.get_key("MONGO_URI")
+ else:
+ udB.set_key("MONGO_URI", "")
+ LOGS.error("PLeasde set a MONGO_URI")
+
+
+@ultroid_cmd(pattern="repoai")
+async def im_oracle(event):
+ if event.reply_to:
+ message = (await event.get_reply_message()).text.strip()
+ else:
+ try:
+ message = event.text.split(" ", 1)[1]
+ except IndexError:
+ return await eod(event, get_string("tban_1"), time=10)
+ reply_ = await get_oracle_reply(
+ query=message, user_id=ultroid_bot.me.id, mongo_url=mongouri
+ )
+ await event.eor(reply_)
+
+
+@ultroid_cmd(pattern="addoai")
+async def add_oracle(event):
+ await oracle_bot_fn(event, type_="add")
+
+
+@ultroid_cmd(pattern="remoai")
+async def rem_oracle(event):
+ await oracle_bot_fn(event, type_="remov")
+
+
+@ultroid_cmd(pattern="listoai")
+async def listoracle(event):
+ key = udB.get_key("ORACLE_USERS") or {}
+ users = key.get(event.chat_id, [])
+ if not users:
+ return await event.eor(get_string("chab_2"), time=5)
+ msg = "**Total List Of Oracle Enabled Users In This Chat :**\n\n"
+ for i in users:
+ try:
+ user = await event.client.get_entity(int(i))
+ user = inline_mention(user)
+ except BaseException:
+ user = f"`{i}`"
+ msg += f"• {user}\n"
+ await event.eor(msg, link_preview=False)
+
+
+async def oracle_bot_fn(event, type_):
+ if event.reply_to:
+ user_ = (await event.get_reply_message()).sender
+ else:
+ temp = event.text.split(maxsplit=1)
+ try:
+ user_ = await event.client.get_entity(await event.client.parse_id(temp[1]))
+ except BaseException as er:
+ LOGS.exception(er)
+ user_ = event.chat if event.is_private else None
+ if not user_:
+ return await eod(
+ event,
+ get_string("chab_1"),
+ )
+ key = udB.get_key("ORACLE_USERS") or {}
+ chat = event.chat_id
+ user = user_.id
+ if type_ == "add":
+ if key.get(chat):
+ if user not in key[chat]:
+ key[chat].append(user)
+ else:
+ key.update({chat: [user]})
+ elif type_ == "remov":
+ if key.get(chat):
+ if user in key[chat]:
+ key[chat].remove(user)
+ if chat in key and not key[chat]:
+ del key[chat]
+ udB.set_key("ORACLE_USERS", key)
+ await event.eor(f"**Oracle:**\n{type_}ed {inline_mention(user_)}")
+
+
+@ultroid_cmd(pattern="repai")
+async def im_lonely_chat_with_me(event):
+ if event.reply_to:
+ message = (await event.get_reply_message()).message
+ else:
+ try:
+ message = event.text.split(" ", 1)[1]
+ except IndexError:
+ return await eod(event, get_string("tban_1"), time=10)
+ reply_ = await get_chatbot_reply(message=message)
+ await event.eor(reply_)
+
+
+@ultroid_cmd(pattern="addai")
+async def add_chatBot(event):
+ await chat_bot_fn(event, type_="add")
+
+
+@ultroid_cmd(pattern="remai")
+async def rem_chatBot(event):
+ await chat_bot_fn(event, type_="remov")
+
+
+@ultroid_cmd(pattern="listai")
+async def lister(event):
+ key = udB.get_key("CHATBOT_USERS") or {}
+ users = key.get(event.chat_id, [])
+ if not users:
+ return await event.eor(get_string("chab_2"), time=5)
+ msg = "**Total List Of AI Enabled Users In This Chat :**\n\n"
+ for i in users:
+ try:
+ user = await event.client.get_entity(int(i))
+ user = inline_mention(user)
+ except BaseException:
+ user = f"`{i}`"
+ msg += f"• {user}\n"
+ await event.eor(msg, link_preview=False)
+
+
+async def chat_bot_fn(event, type_):
+ if event.reply_to:
+ user_ = (await event.get_reply_message()).sender
+ else:
+ temp = event.text.split(maxsplit=1)
+ try:
+ user_ = await event.client.get_entity(await event.client.parse_id(temp[1]))
+ except BaseException as er:
+ LOGS.exception(er)
+ user_ = event.chat if event.is_private else None
+ if not user_:
+ return await eod(
+ event,
+ get_string("chab_1"),
+ )
+ key = udB.get_key("CHATBOT_USERS") or {}
+ chat = event.chat_id
+ user = user_.id
+ if type_ == "add":
+ if key.get(chat):
+ if user not in key[chat]:
+ key[chat].append(user)
+ else:
+ key.update({chat: [user]})
+ elif type_ == "remov":
+ if key.get(chat):
+ if user in key[chat]:
+ key[chat].remove(user)
+ if chat in key and not key[chat]:
+ del key[chat]
+ udB.set_key("CHATBOT_USERS", key)
+ await event.eor(f"**ChatBot:**\n{type_}ed {inline_mention(user_)}")
diff --git a/plugins/chats.py b/plugins/chats.py
new file mode 100644
index 0000000000000000000000000000000000000000..2ef171b1de3fd9f5ac67936cd116d1c9885189fe
--- /dev/null
+++ b/plugins/chats.py
@@ -0,0 +1,368 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+from . import get_help
+
+__doc__ = get_help("help_chats")
+
+
+from telethon.errors import ChatAdminRequiredError as no_admin
+from telethon.tl.functions.channels import (
+ CreateChannelRequest,
+ DeleteChannelRequest,
+ EditPhotoRequest,
+ GetFullChannelRequest,
+ UpdateUsernameRequest,
+)
+from telethon.tl.functions.messages import (
+ CreateChatRequest,
+ ExportChatInviteRequest,
+ GetFullChatRequest,
+)
+from telethon.tl.types import (
+ ChannelParticipantsKicked,
+ User,
+ UserStatusEmpty,
+ UserStatusLastMonth,
+ UserStatusLastWeek,
+ UserStatusOffline,
+ UserStatusOnline,
+ UserStatusRecently,
+)
+
+from . import HNDLR, LOGS, asst, con, get_string, mediainfo, os, types, udB, ultroid_cmd
+
+
+@ultroid_cmd(
+ pattern="delchat",
+ groups_only=True,
+)
+async def _(e):
+ xx = await e.eor(get_string("com_1"))
+ try:
+ match = e.text.split(" ", maxsplit=1)[1]
+ chat = await e.client.parse_id(match)
+ except IndexError:
+ chat = e.chat_id
+ try:
+ await e.client(DeleteChannelRequest(chat))
+ except TypeError:
+ return await xx.eor(get_string("chats_1"), time=10)
+ except no_admin:
+ return await xx.eor(get_string("chats_2"), time=10)
+ await e.client.send_message(
+ int(udB.get_key("LOG_CHANNEL")), get_string("chats_6").format(e.chat_id)
+ )
+
+
+@ultroid_cmd(
+ pattern="getlink( (.*)|$)",
+ groups_only=True,
+ manager=True,
+)
+async def _(e):
+ reply = await e.get_reply_message()
+ match = e.pattern_match.group(1).strip()
+ if reply and not isinstance(reply.sender, User):
+ chat = await reply.get_sender()
+ else:
+ chat = await e.get_chat()
+ if hasattr(chat, "username") and chat.username:
+ return await e.eor(f"Username: @{chat.username}")
+ request, usage, title, link = None, None, None, None
+ if match:
+ split = match.split(maxsplit=1)
+ request = split[0] in ["r", "request"]
+ title = "Created by Ultroid"
+ if len(split) > 1:
+ match = split[1]
+ spli = match.split(maxsplit=1)
+ if spli[0].isdigit():
+ usage = int(spli[0])
+ if len(spli) > 1:
+ title = spli[1]
+ elif not request:
+ if match.isdigit():
+ usage = int(match)
+ else:
+ title = match
+ if request and usage:
+ usage = 0
+ if request or title:
+ try:
+ r = await e.client(
+ ExportChatInviteRequest(
+ e.chat_id,
+ request_needed=request,
+ usage_limit=usage,
+ title=title,
+ ),
+ )
+ except no_admin:
+ return await e.eor(get_string("chats_2"), time=10)
+ link = r.link
+ else:
+ if isinstance(chat, types.Chat):
+ FC = await e.client(GetFullChatRequest(chat.id))
+ elif isinstance(chat, types.Channel):
+ FC = await e.client(GetFullChannelRequest(chat.id))
+ else:
+ return
+ Inv = FC.full_chat.exported_invite
+ if Inv and not Inv.revoked:
+ link = Inv.link
+ if link:
+ return await e.eor(f"Link:- {link}")
+ await e.eor("`Failed to getlink!\nSeems like link is inaccessible to you...`")
+
+
+@ultroid_cmd(
+ pattern="create (b|g|c)(?: |$)(.*)",
+)
+async def _(e):
+ type_of_group = e.pattern_match.group(1).strip()
+ group_name = e.pattern_match.group(2)
+ username = None
+ if " ; " in group_name:
+ group_ = group_name.split(" ; ", maxsplit=1)
+ group_name = group_[0]
+ username = group_[1]
+ xx = await e.eor(get_string("com_1"))
+ if type_of_group == "b":
+ try:
+ r = await e.client(
+ CreateChatRequest(
+ users=[asst.me.username],
+ title=group_name,
+ ),
+ )
+ created_chat_id = r.chats[0].id
+ result = await e.client(
+ ExportChatInviteRequest(
+ peer=created_chat_id,
+ ),
+ )
+ await xx.edit(
+ get_string("chats_4").format(group_name, result.link),
+ link_preview=False,
+ )
+ except Exception as ex:
+ await xx.edit(str(ex))
+ elif type_of_group in ["g", "c"]:
+ try:
+ r = await e.client(
+ CreateChannelRequest(
+ title=group_name,
+ about=get_string("chats_5"),
+ megagroup=type_of_group != "c",
+ )
+ )
+
+ created_chat_id = r.chats[0].id
+ if username:
+ await e.client(UpdateUsernameRequest(created_chat_id, username))
+ result = f"https://t.me/{username}"
+ else:
+ result = (
+ await e.client(
+ ExportChatInviteRequest(
+ peer=created_chat_id,
+ ),
+ )
+ ).link
+ await xx.edit(
+ get_string("chats_6").format(f"[{group_name}]({result})"),
+ link_preview=False,
+ )
+ except Exception as ex:
+ await xx.edit(str(ex))
+
+
+# ---------------------------------------------------------------- #
+
+
+@ultroid_cmd(
+ pattern="setgpic( (.*)|$)", admins_only=True, manager=True, require="change_info"
+)
+async def _(ult):
+ if not ult.is_reply:
+ return await ult.eor("`Reply to a Media..`", time=5)
+ match = ult.pattern_match.group(1).strip()
+ if not ult.client._bot and match:
+ try:
+ chat = await ult.client.parse_id(match)
+ except Exception as ok:
+ return await ult.eor(str(ok))
+ else:
+ chat = ult.chat_id
+ reply = await ult.get_reply_message()
+ if reply.photo or reply.sticker or reply.video:
+ replfile = await reply.download_media()
+ elif reply.document and reply.document.thumbs:
+ replfile = await reply.download_media(thumb=-1)
+ else:
+ return await ult.eor("Reply to a Photo or Video..")
+ mediain = mediainfo(reply.media)
+ if "animated" in mediain:
+ replfile = await con.convert(replfile, convert_to="mp4")
+ else:
+ replfile = await con.convert(
+ replfile, outname="chatphoto", allowed_formats=["jpg", "png", "mp4"]
+ )
+ file = await ult.client.upload_file(replfile)
+ try:
+ if "pic" not in mediain:
+ file = types.InputChatUploadedPhoto(video=file)
+ await ult.client(EditPhotoRequest(chat, file))
+ await ult.eor("`Group Photo has Successfully Changed !`", time=5)
+ except Exception as ex:
+ await ult.eor(f"Error occured.\n`{str(ex)}`", time=5)
+ os.remove(replfile)
+
+
+@ultroid_cmd(
+ pattern="delgpic( (.*)|$)", admins_only=True, manager=True, require="change_info"
+)
+async def _(ult):
+ match = ult.pattern_match.group(1).strip()
+ chat = ult.chat_id
+ if not ult.client._bot and match:
+ chat = match
+ try:
+ await ult.client(EditPhotoRequest(chat, types.InputChatPhotoEmpty()))
+ text = "`Removed Chat Photo..`"
+ except Exception as E:
+ text = str(E)
+ return await ult.eor(text, time=5)
+
+
+@ultroid_cmd(pattern="unbanall$", manager=True, admins_only=True, require="ban_users")
+async def _(event):
+ xx = await event.eor("Searching Participant Lists.")
+ p = 0
+ title = (await event.get_chat()).title
+ async for i in event.client.iter_participants(
+ event.chat_id,
+ filter=ChannelParticipantsKicked,
+ aggressive=True,
+ ):
+ try:
+ await event.client.edit_permissions(event.chat_id, i, view_messages=True)
+ p += 1
+ except no_admin:
+ pass
+ except BaseException as er:
+ LOGS.exception(er)
+ await xx.eor(f"{title}: {p} unbanned", time=5)
+
+
+@ultroid_cmd(
+ pattern="rmusers( (.*)|$)",
+ groups_only=True,
+ admins_only=True,
+ fullsudo=True,
+)
+async def _(event):
+ xx = await event.eor(get_string("com_1"))
+ input_str = event.pattern_match.group(1).strip()
+ p, a, b, c, d, m, n, y, w, o, q, r = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ async for i in event.client.iter_participants(event.chat_id):
+ p += 1 # Total Count
+ if isinstance(i.status, UserStatusEmpty):
+ if "empty" in input_str:
+ try:
+ await event.client.kick_participant(event.chat_id, i)
+ c += 1
+ except BaseException:
+ pass
+ else:
+ y += 1
+ if isinstance(i.status, UserStatusLastMonth):
+ if "month" in input_str:
+ try:
+ await event.client.kick_participant(event.chat_id, i)
+ c += 1
+ except BaseException:
+ pass
+ else:
+ m += 1
+ if isinstance(i.status, UserStatusLastWeek):
+ if "week" in input_str:
+ try:
+ await event.client.kick_participant(event.chat_id, i)
+ c += 1
+ except BaseException:
+ pass
+ else:
+ w += 1
+ if isinstance(i.status, UserStatusOffline):
+ if "offline" in input_str:
+ try:
+ await event.client.kick_participant(event.chat_id, i)
+ c += 1
+ except BaseException:
+ pass
+ else:
+ o += 1
+ if isinstance(i.status, UserStatusOnline):
+ if "online" in input_str:
+ try:
+ await event.client.kick_participant(event.chat_id, i)
+ c += 1
+ except BaseException:
+ pass
+ else:
+ q += 1
+ if isinstance(i.status, UserStatusRecently):
+ if "recently" in input_str:
+ try:
+ await event.client.kick_participant(event.chat_id, i)
+ c += 1
+ except BaseException:
+ pass
+ else:
+ r += 1
+ if i.bot:
+ if "bot" in input_str:
+ try:
+ await event.client.kick_participant(event.chat_id, i)
+ c += 1
+ except BaseException:
+ pass
+ else:
+ b += 1
+ elif i.deleted:
+ if "deleted" in input_str:
+ try:
+ await event.client.kick_participant(event.chat_id, i)
+ c += 1
+ except BaseException:
+ pass
+ else:
+ d += 1
+ elif i.status is None:
+ if "none" in input_str:
+ try:
+ await event.client.kick_participant(event.chat_id, i)
+ c += 1
+ except BaseException:
+ pass
+ else:
+ n += 1
+ if input_str:
+ required_string = f"**>> Kicked** `{c} / {p}` **users**\n\n"
+ else:
+ required_string = f"**>> Total** `{p}` **users**\n\n"
+ required_string += f" `{HNDLR}rmusers deleted` **••** `{d}`\n"
+ required_string += f" `{HNDLR}rmusers empty` **••** `{y}`\n"
+ required_string += f" `{HNDLR}rmusers month` **••** `{m}`\n"
+ required_string += f" `{HNDLR}rmusers week` **••** `{w}`\n"
+ required_string += f" `{HNDLR}rmusers offline` **••** `{o}`\n"
+ required_string += f" `{HNDLR}rmusers online` **••** `{q}`\n"
+ required_string += f" `{HNDLR}rmusers recently` **••** `{r}`\n"
+ required_string += f" `{HNDLR}rmusers bot` **••** `{b}`\n"
+ required_string += f" `{HNDLR}rmusers none` **••** `{n}`"
+ await xx.eor(required_string)
diff --git a/plugins/cleanaction.py b/plugins/cleanaction.py
new file mode 100644
index 0000000000000000000000000000000000000000..ebc65752f3267e175da561ea383edc31cb5bfa20
--- /dev/null
+++ b/plugins/cleanaction.py
@@ -0,0 +1,48 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_cleanaction")
+
+
+from telethon.utils import get_display_name
+
+from . import get_string, udB, ultroid_cmd
+
+
+@ultroid_cmd(pattern="addclean$", admins_only=True)
+async def _(e):
+ key = udB.get_key("CLEANCHAT") or []
+ if e.chat_id in key:
+ return await eod(e, get_string("clan_5"))
+ key.append(e.chat_id)
+ udB.set_key("CLEANCHAT", key)
+ await e.eor(get_string("clan_1"), time=5)
+
+
+@ultroid_cmd(pattern="remclean$")
+async def _(e):
+ key = udB.get_key("CLEANCHAT") or []
+ if e.chat_id in key:
+ key.remove(e.chat_id)
+ udB.set_key("CLEANCHAT", key)
+ await e.eor(get_string("clan_2"), time=5)
+
+
+@ultroid_cmd(pattern="listclean$")
+async def _(e):
+ if k := udB.get_key("CLEANCHAT"):
+ o = ""
+ for x in k:
+ try:
+ title = get_display_name(await e.client.get_entity(x))
+ except BaseException:
+ title = get_string("clan_3")
+ o += f"{x} {title}\n"
+ return await e.eor(o)
+ await e.eor(get_string("clan_4"), time=5)
diff --git a/plugins/codefix.py b/plugins/codefix.py
new file mode 100644
index 0000000000000000000000000000000000000000..1340eabeacb96651cdf196fc8ddd93274af246a1
--- /dev/null
+++ b/plugins/codefix.py
@@ -0,0 +1,241 @@
+import os
+from collections import deque
+from io import BytesIO
+
+from . import (
+ ultroid_cmd,
+ async_searcher,
+ udB,
+ LOGS,
+ get_paste,
+)
+
+CR_O_CHAT_HISTORY = deque(maxlen=30)
+
+TELEGRAM_CHAR_LIMIT = 4096 # Telegram's message character limit
+
+initprompt = """
+You are an expert coding assistant. Your primary goal is to analyze, repair, and enhance the code provided by the user.
+
+Follow this structured approach:
+
+1. **Clarify Code Intent:**
+ * If the purpose of the code is unclear, ask the user for clarification.
+ * Understand what the code is supposed to achieve.
+
+2. **Analyze and Diagnose:**
+ * Identify errors, bugs, security vulnerabilities, or logical flaws.
+ * Look for performance inefficiencies and suggest improvements.
+ * Ensure adherence to coding standards and best practices (e.g., PEP 8 for Python).
+
+3. **Repair and Optimize:**
+ * Correct bugs, errors, and vulnerabilities, providing explanations for each fix.
+ * Optimize the code for speed, memory usage, or overall efficiency.
+ * Recommend alternative libraries or methods where they might offer better solutions.
+
+4. **Enhance Readability and Maintainability:**
+ * Apply consistent formatting and clean coding practices.
+ * Add meaningful comments to clarify complex logic or structures.
+
+5. **Summarize Improvements:**
+ * Present the corrected, optimized code.
+ * Provide a brief summary of the changes made and explain the benefits of each.
+"""
+
+initset = False
+
+async def pastee(data):
+ err, linky = await get_paste(data)
+ if err:
+ return f">> [Raw Code Pasted Here](https://spaceb.in/{linky})\n"
+ else:
+ LOGS.error(linky)
+ return ""
+
+
+@ultroid_cmd(
+ pattern=r"codefix( ([\s\S]*))?$",
+)
+async def openai_chat_gpt(e):
+ global initset
+ api_key = "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"
+ if not api_key:
+ return await e.eor("`OPENAI_API` key missing..", time=10)
+
+ query = e.pattern_match.group(2)
+ reply = await e.get_reply_message()
+
+ file_content = None
+
+ if query:
+ # Check if query contains 'from filename'
+ if ' from ' in query:
+ query_text, filename = query.split(' from ', 1)
+ query_text = query_text.strip()
+ filename = filename.strip()
+ # Attempt to find and read the file from media in chat
+ file_found = False
+ async for message in e.client.iter_messages(e.chat_id, reverse=True, limit=50):
+ if message.media and message.file.name == filename:
+ if (message.file.name.endswith(".txt") or message.file.name.endswith(".py")):
+ file = await e.client.download_media(message)
+ try:
+ with open(file, "r", encoding='utf-8') as f:
+ file_content = f.read()
+ except Exception as exc:
+ LOGS.error(f"Error reading file: {exc}")
+ return await e.eor("`Failed to read file content.`", time=5)
+ finally:
+ os.remove(file)
+ file_found = True
+ break
+ if not file_found:
+ return await e.eor(f"`File {filename} not found in recent messages.`", time=5)
+ if file_content:
+ query = f"{query_text}\n\n{file_content}" if query_text else file_content
+ else:
+ return await e.eor("`Failed to read file content.`", time=5)
+ else:
+ if reply and reply.media and (reply.file.name.endswith(".txt") or reply.file.name.endswith(".py")):
+ # Use the query and the replied file content
+ file = await e.client.download_media(reply)
+ try:
+ with open(file, "r", encoding='utf-8') as f:
+ file_content = f.read()
+ except Exception as exc:
+ LOGS.error(f"Error reading file: {exc}")
+ return await e.eor("`Failed to read file content.`", time=5)
+ finally:
+ os.remove(file)
+ query = f"{query}\n\n{file_content}"
+ elif reply and reply.message:
+ # Use the query and the replied text message content
+ query = f"{query}\n\n{reply.message}"
+ # Else, use query as is
+ else:
+ if reply and reply.media and (reply.file.name.endswith(".txt") or reply.file.name.endswith(".py")):
+ # Use the replied file content
+ file = await e.client.download_media(reply)
+ try:
+ with open(file, "r", encoding='utf-8') as f:
+ file_content = f.read()
+ except Exception as exc:
+ LOGS.error(f"Error reading file: {exc}")
+ return await e.eor("`Failed to read file content.`", time=5)
+ finally:
+ os.remove(file)
+ query = file_content
+ elif reply and reply.message:
+ # Use the replied text message content
+ query = reply.message
+ else:
+ return await e.eor("`Please provide a question or reply to a message or .txt/.py file.`", time=5)
+
+ if query.strip() == "-c":
+ initset = False
+ CR_O_CHAT_HISTORY.clear()
+ return await e.eor("__Cleared o1-mini Chat History!__", time=6)
+
+ if initset == False:
+ CR_O_CHAT_HISTORY.append({"role": "user", "content": initprompt})
+ try:
+ data = {
+ "model": "o1-mini",
+ "messages": list(CR_O_CHAT_HISTORY),
+ }
+ request = await async_searcher(
+ "https://api.openai.com/v1/chat/completions",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {api_key}",
+ },
+ json=data,
+ re_json=True,
+ post=True,
+ )
+ response = request["choices"][0]["message"]["content"]
+ CR_O_CHAT_HISTORY.append({"role": "assistant", "content": response})
+ initset = True
+ except Exception as exc:
+ LOGS.warning(exc, exc_info=True)
+ CR_O_CHAT_HISTORY.pop()
+ return await e.edit(
+ f"**Error while requesting data from OpenAI:** \n> `{exc}`"
+ )
+
+ eris = await e.eor(f"__Generating answer for:__\n`{query[:20]} ...`")
+ CR_O_CHAT_HISTORY.append({"role": "user", "content": query})
+
+ try:
+ data = {
+ "model": "o1-mini",
+ "messages": list(CR_O_CHAT_HISTORY),
+ }
+ request = await async_searcher(
+ "https://api.openai.com/v1/chat/completions",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {api_key}",
+ },
+ json=data,
+ re_json=True,
+ post=True,
+ )
+ response = request["choices"][0]["message"]["content"]
+ CR_O_CHAT_HISTORY.append({"role": "assistant", "content": response})
+ except Exception as exc:
+ LOGS.warning(exc, exc_info=True)
+ CR_O_CHAT_HISTORY.pop()
+ return await eris.edit(
+ f"**Error while requesting data from OpenAI:** \n> `{exc}`"
+ )
+
+ LOGS.debug(f'Tokens Used on query: {request["usage"]["completion_tokens"]}')
+
+ # Truncate query to 50 characters for display
+ truncated_query = query[:100]
+
+ # Prepare the full message
+ full_message = f"**Query:**\n~ __{truncated_query}__\n\n**o1-mini:**\n~ {response}"
+
+ # Check if response contains code blocks
+ code_blocks = []
+ in_code_block = False
+ code_block_lines = []
+ for line in response.split('\n'):
+ if line.strip().startswith('```'):
+ if in_code_block:
+ # End of code block
+ in_code_block = False
+ code_blocks.append('\n'.join(code_block_lines))
+ code_block_lines = []
+ else:
+ # Start of code block
+ in_code_block = True
+ elif in_code_block:
+ code_block_lines.append(line)
+
+ # If the response contains code blocks, select the largest one and paste it
+ if code_blocks:
+ # Select the largest code block based on length
+ largest_code_block = max(code_blocks, key=lambda block: len(block))
+ # Upload the largest code block to spaceb.in and get the link
+ paste_link = await pastee(largest_code_block)
+ else:
+ paste_link = ""
+
+ if len(full_message) <= TELEGRAM_CHAR_LIMIT:
+ # If it fits within the limit, send as a message
+ await eris.edit(full_message + f"\n\n{paste_link}")
+ else:
+ # If it exceeds the limit, send as a file and include paste link
+ file = BytesIO(full_message.encode('utf-8'))
+ file.name = "o1-mini-output.txt"
+ await eris.respond(
+ "__The query and response were too long, so they have been sent as a file.__\n\n" + paste_link,
+ file=file,
+ reply_to=e.reply_to_msg_id or e.id,
+ link_preview=False
+ )
+ await eris.delete()
+
diff --git a/plugins/codegpt.py b/plugins/codegpt.py
new file mode 100644
index 0000000000000000000000000000000000000000..ca3b6d545ac389119aaddd155722c1bc9852aa0d
--- /dev/null
+++ b/plugins/codegpt.py
@@ -0,0 +1,302 @@
+import os
+from collections import deque
+from io import BytesIO
+
+from . import (
+ ultroid_cmd,
+ async_searcher,
+ udB,
+ LOGS,
+ get_paste,
+)
+
+CG_GPT_CHAT_HISTORY = deque(maxlen=30)
+
+TELEGRAM_CHAR_LIMIT = 4096 # Telegram's message character limit
+
+initprompt = """
+Your name is User Coding Helper. Your task is to create plugins for the Ultroid Telegram userbot. Follow these guidelines:
+1. Imports: Include all necessary imports as demonstrated in the example code provided below.
+2. Command Creation: Generate a random, suitable Ultroid command. Ensure that this command can either:
+ - Process a query, or
+ - Be used directly with the command.
+3. Code Submission: Do not send any code without a corresponding post request or without the user providing a code snippet.
+
+Example Code:
+```
+from os import system, remove
+from io import BytesIO
+
+try:
+ import openai
+except ImportError:
+ system("pip install -q openai")
+ import openai
+
+from . import ultroid_cmd, check_filename, udB, LOGS, fast_download, run_async
+
+@run_async
+def get_gpt_answer(gen_image, question, api_key):
+ openai.api_key = api_key
+ if gen_image:
+ x = openai.Image.create(
+ prompt=question,
+ n=1,
+ size="1024x1024",
+ user="arc",
+ )
+ return x["data"][0]["url"]
+ x = openai.ChatCompletion.create(
+ model="gpt-3.5-turbo",
+ messages=[{"role": "user", "content": question}],
+ )
+ LOGS.debug(f'Token Used on ({question}) > {x["usage"]["total_tokens"]}')
+ return x["choices"][0]["message"]["content"].lstrip("+AFw-n")
+
+@ultroid_cmd(pattern="(chat)?gpt( (.*)|$)")
+async def openai_chat_gpt(e):
+ api_key = udB.get_key("OPENAI_API")
+ gen_image = False
+ if not api_key:
+ return await e.eor("OPENAI_API key missing..")
+
+ args = e.pattern_match.group(3)
+ reply = await e.get_reply_message()
+ if not args:
+ if reply and reply.text:
+ args = reply.message
+ if not args:
+ return await e.eor("Gimme a Question to ask from ChatGPT")
+
+ moi = await e.eor(f"+2D3cIw")
+ if args.startswith("-i"):
+ gen_image = True
+ args = args[2:].strip()
+ try:
+ response = await get_gpt_answer(gen_image, args, api_key)
+ except Exception as exc:
+ LOGS.warning(exc, exc_info=True)
+ return await moi.edit(f"Error: +AFw-n> {exc}")
+ else:
+ if gen_image:
+ path, _ = await fast_download(
+ response, filename=check_filename("dall-e.png")
+ )
+ await e.client.send_file(
+ e.chat_id,
+ path,
+ caption=f"{args[:1020]}",
+ reply_to=e.reply_to_msg_id,
+ )
+ await moi.delete()
+ return remove(path)
+ if len(response) < 4095:
+ answer = f"+AFw-n {response}"
+ return await moi.edit(answer, parse_mode="html")
+ with BytesIO(response.encode()) as file:
+ file.name = "gpt_response.txt"
+ await e.client.send_file(
+ e.chat_id, file, caption=f"{args[:1020]}", reply_to=e.reply_to_msg_id
+ )
+ await moi.delete()
+```
+
+Based on this template, whenever a new prompt is given, create a suitable Ultroid plugin code snippet that includes a POST request, handles the query, and assigns a new command.
+"""
+
+initset = False
+
+async def pastee(data):
+ err, linky = await get_paste(data)
+ if err:
+ return f">> [Raw Code Pasted Here](https://spaceb.in/{linky})\n"
+ else:
+ LOGS.error(linky)
+ return ""
+
+
+@ultroid_cmd(
+ pattern=r"codegen( ([\s\S]*))?$",
+)
+async def openai_chat_gpt(e):
+ global initset
+ api_key = "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"
+ if not api_key:
+ return await e.eor("`OPENAI_API` key missing..", time=10)
+
+ query = e.pattern_match.group(2)
+ reply = await e.get_reply_message()
+
+ file_content = None
+
+ if query:
+ # Check if query contains 'from filename'
+ if ' from ' in query:
+ query_text, filename = query.split(' from ', 1)
+ query_text = query_text.strip()
+ filename = filename.strip()
+ # Attempt to find and read the file from media in chat
+ file_found = False
+ async for message in e.client.iter_messages(e.chat_id, reverse=True, limit=50):
+ if message.media and message.file.name == filename:
+ if (message.file.name.endswith(".txt") or message.file.name.endswith(".py")):
+ file = await e.client.download_media(message)
+ try:
+ with open(file, "r", encoding='utf-8') as f:
+ file_content = f.read()
+ except Exception as exc:
+ LOGS.error(f"Error reading file: {exc}")
+ return await e.eor("`Failed to read file content.`", time=5)
+ finally:
+ os.remove(file)
+ file_found = True
+ break
+ if not file_found:
+ return await e.eor(f"`File {filename} not found in recent messages.`", time=5)
+ if file_content:
+ query = f"{query_text}\n\n{file_content}" if query_text else file_content
+ else:
+ return await e.eor("`Failed to read file content.`", time=5)
+ else:
+ if reply and reply.media and (reply.file.name.endswith(".txt") or reply.file.name.endswith(".py")):
+ # Use the query and the replied file content
+ file = await e.client.download_media(reply)
+ try:
+ with open(file, "r", encoding='utf-8') as f:
+ file_content = f.read()
+ except Exception as exc:
+ LOGS.error(f"Error reading file: {exc}")
+ return await e.eor("`Failed to read file content.`", time=5)
+ finally:
+ os.remove(file)
+ query = f"{query}\n\n{file_content}"
+ elif reply and reply.message:
+ # Use the query and the replied text message content
+ query = f"{query}\n\n{reply.message}"
+ # Else, use query as is
+ else:
+ if reply and reply.media and (reply.file.name.endswith(".txt") or reply.file.name.endswith(".py")):
+ # Use the replied file content
+ file = await e.client.download_media(reply)
+ try:
+ with open(file, "r", encoding='utf-8') as f:
+ file_content = f.read()
+ except Exception as exc:
+ LOGS.error(f"Error reading file: {exc}")
+ return await e.eor("`Failed to read file content.`", time=5)
+ finally:
+ os.remove(file)
+ query = file_content
+ elif reply and reply.message:
+ # Use the replied text message content
+ query = reply.message
+ else:
+ return await e.eor("`Please provide a question or reply to a message or .txt/.py file.`", time=5)
+
+ if query.strip() == "-c":
+ CG_GPT_CHAT_HISTORY.clear()
+ return await e.eor("__Cleared o1-mini Chat History!__", time=6)
+
+ if initset == False:
+ CG_GPT_CHAT_HISTORY.append({"role": "user", "content": initprompt})
+ try:
+ data = {
+ "model": "o1-mini",
+ "messages": list(CG_GPT_CHAT_HISTORY),
+ }
+ request = await async_searcher(
+ "https://api.openai.com/v1/chat/completions",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {api_key}",
+ },
+ json=data,
+ re_json=True,
+ post=True,
+ )
+ response = request["choices"][0]["message"]["content"]
+ CG_GPT_CHAT_HISTORY.append({"role": "assistant", "content": response})
+ initset = True
+ except Exception as exc:
+ LOGS.warning(exc, exc_info=True)
+ CG_GPT_CHAT_HISTORY.pop()
+ return await eris.edit(
+ f"**Error while requesting data from OpenAI:** \n> `{exc}`"
+ )
+
+ eris = await e.eor(f"__Generating answer for:__\n`{query[:20]} ...`")
+ CG_GPT_CHAT_HISTORY.append({"role": "user", "content": query})
+
+ try:
+ data = {
+ "model": "o1-mini",
+ "messages": list(CG_GPT_CHAT_HISTORY),
+ }
+ request = await async_searcher(
+ "https://api.openai.com/v1/chat/completions",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {api_key}",
+ },
+ json=data,
+ re_json=True,
+ post=True,
+ )
+ response = request["choices"][0]["message"]["content"]
+ CG_GPT_CHAT_HISTORY.append({"role": "assistant", "content": response})
+ except Exception as exc:
+ LOGS.warning(exc, exc_info=True)
+ CG_GPT_CHAT_HISTORY.pop()
+ return await eris.edit(
+ f"**Error while requesting data from OpenAI:** \n> `{exc}`"
+ )
+
+ LOGS.debug(f'Tokens Used on query: {request["usage"]["completion_tokens"]}')
+
+ # Truncate query to 50 characters for display
+ truncated_query = query[:100]
+
+ # Prepare the full message
+ full_message = f"**Query:**\n~ __{truncated_query}__\n\n**o1-mini:**\n~ {response}"
+
+ # Check if response contains code blocks
+ code_blocks = []
+ in_code_block = False
+ code_block_lines = []
+ for line in response.split('\n'):
+ if line.strip().startswith('```'):
+ if in_code_block:
+ # End of code block
+ in_code_block = False
+ code_blocks.append('\n'.join(code_block_lines))
+ code_block_lines = []
+ else:
+ # Start of code block
+ in_code_block = True
+ elif in_code_block:
+ code_block_lines.append(line)
+
+ # If the response contains code blocks, select the largest one and paste it
+ if code_blocks:
+ # Select the largest code block based on length
+ largest_code_block = max(code_blocks, key=lambda block: len(block))
+ # Upload the largest code block to spaceb.in and get the link
+ paste_link = await pastee(largest_code_block)
+ else:
+ paste_link = ""
+
+ if len(full_message) <= TELEGRAM_CHAR_LIMIT:
+ # If it fits within the limit, send as a message
+ await eris.edit(full_message + f"\n\n{paste_link}")
+ else:
+ # If it exceeds the limit, send as a file and include paste link
+ file = BytesIO(full_message.encode('utf-8'))
+ file.name = "o1-mini-output.txt"
+ await eris.respond(
+ "__The query and response were too long, so they have been sent as a file.__\n\n" + paste_link,
+ file=file,
+ reply_to=e.reply_to_msg_id or e.id,
+ link_preview=False
+ )
+ await eris.delete()
+
diff --git a/plugins/compressor.py b/plugins/compressor.py
new file mode 100644
index 0000000000000000000000000000000000000000..4161a9f4fa6d397ccd225ceda0ef031f80458a1b
--- /dev/null
+++ b/plugins/compressor.py
@@ -0,0 +1,175 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_compressor")
+
+
+import asyncio
+import os
+import re
+import time
+from datetime import datetime as dt
+
+from telethon.errors.rpcerrorlist import MessageNotModifiedError
+from telethon.tl.types import DocumentAttributeVideo
+
+from pyUltroid.fns.tools import metadata
+
+from . import (
+ ULTConfig,
+ bash,
+ downloader,
+ get_string,
+ humanbytes,
+ math,
+ mediainfo,
+ time_formatter,
+ ultroid_cmd,
+ uploader,
+)
+
+
+@ultroid_cmd(pattern="compress( (.*)|$)")
+async def _(e):
+ cr = e.pattern_match.group(1).strip()
+ crf = 27
+ to_stream = False
+ if cr:
+ k = e.text.split()
+ if len(k) == 2:
+ crf = int(k[1]) if k[1].isdigit() else 27
+ elif len(k) > 2:
+ crf = int(k[1]) if k[1].isdigit() else 27
+ to_stream = "stream" in k[2]
+ vido = await e.get_reply_message()
+ if vido and vido.media and "video" in mediainfo(vido.media):
+ if hasattr(vido.media, "document"):
+ vfile = vido.media.document
+ name = vido.file.name
+ else:
+ vfile = vido.media
+ name = ""
+ if not name:
+ name = "video_" + dt.now().isoformat("_", "seconds") + ".mp4"
+ xxx = await e.eor(get_string("audiotools_5"))
+ c_time = time.time()
+ file = await downloader(
+ f"resources/downloads/{name}",
+ vfile,
+ xxx,
+ c_time,
+ f"Downloading {name}...",
+ )
+
+ o_size = os.path.getsize(file.name)
+ d_time = time.time()
+ diff = time_formatter((d_time - c_time) * 1000)
+ file_name = (file.name).split("/")[-1]
+ out = file_name.replace(file_name.split(".")[-1], "compressed.mkv")
+ await xxx.edit(
+ f"`Downloaded {file.name} of {humanbytes(o_size)} in {diff}.\nNow Compressing...`"
+ )
+ x, y = await bash(
+ f'mediainfo --fullscan """{file.name}""" | grep "Frame count"'
+ )
+ if y and y.endswith("NOT_FOUND"):
+ return await xxx.edit(f"ERROR: `{y}`")
+ total_frames = x.split(":")[1].split("\n")[0]
+ progress = f"progress-{c_time}.txt"
+ with open(progress, "w"):
+ pass
+ proce = await asyncio.create_subprocess_shell(
+ f'ffmpeg -hide_banner -loglevel quiet -progress {progress} -i """{file.name}""" -preset ultrafast -vcodec libx265 -crf {crf} -c:a copy """{out}""" -y',
+ stdout=asyncio.subprocess.PIPE,
+ stderr=asyncio.subprocess.PIPE,
+ )
+ while proce.returncode != 0:
+ await asyncio.sleep(3)
+ with open(progress, "r+") as fil:
+ text = fil.read()
+ frames = re.findall("frame=(\\d+)", text)
+ size = re.findall("total_size=(\\d+)", text)
+ speed = 0
+ if len(frames):
+ elapse = int(frames[-1])
+ if len(size):
+ size = int(size[-1])
+ per = elapse * 100 / int(total_frames)
+ time_diff = time.time() - int(d_time)
+ speed = round(elapse / time_diff, 2)
+ if int(speed) != 0:
+ some_eta = ((int(total_frames) - elapse) / speed) * 1000
+ text = f"`Compressing {file_name} at {crf} CRF.\n`"
+ progress_str = "`[{0}{1}] {2}%\n\n`".format(
+ "".join("●" for _ in range(math.floor(per / 5))),
+ "".join("" for _ in range(20 - math.floor(per / 5))),
+ round(per, 2),
+ )
+
+ e_size = f"{humanbytes(size)} of ~{humanbytes((size / per) * 100)}"
+ eta = f"~{time_formatter(some_eta)}"
+ try:
+ await xxx.edit(
+ text
+ + progress_str
+ + "`"
+ + e_size
+ + "`"
+ + "\n\n`"
+ + eta
+ + "`"
+ )
+ except MessageNotModifiedError:
+ pass
+ os.remove(file.name)
+ c_size = os.path.getsize(out)
+ f_time = time.time()
+ difff = time_formatter((f_time - d_time) * 1000)
+ await xxx.edit(
+ f"`Compressed {humanbytes(o_size)} to {humanbytes(c_size)} in {difff}\nTrying to Upload...`"
+ )
+ differ = 100 - ((c_size / o_size) * 100)
+ caption = f"**Original Size: **`{humanbytes(o_size)}`\n"
+ caption += f"**Compressed Size: **`{humanbytes(c_size)}`\n"
+ caption += f"**Compression Ratio: **`{differ:.2f}%`\n"
+ caption += f"\n**Time Taken To Compress: **`{difff}`"
+ mmmm = await uploader(out, out, f_time, xxx, f"Uploading {out}...")
+ if to_stream:
+ data = await metadata(out)
+ width = data["width"]
+ height = data["height"]
+ duration = data["duration"]
+ attributes = [
+ DocumentAttributeVideo(
+ duration=duration, w=width, h=height, supports_streaming=True
+ )
+ ]
+ await e.client.send_file(
+ e.chat_id,
+ mmmm,
+ thumb=ULTConfig.thumb,
+ caption=caption,
+ attributes=attributes,
+ force_document=False,
+ reply_to=e.reply_to_msg_id,
+ )
+ else:
+ await e.client.send_file(
+ e.chat_id,
+ mmmm,
+ thumb=ULTConfig.thumb,
+ caption=caption,
+ force_document=True,
+ reply_to=e.reply_to_msg_id,
+ )
+ await xxx.delete()
+ os.remove(out)
+ os.remove(progress)
+ else:
+ await e.eor(get_string("audiotools_8"), time=5)
diff --git a/plugins/converter.py b/plugins/converter.py
new file mode 100644
index 0000000000000000000000000000000000000000..0ed3e36037be740b8b23b96ef8f9073644f8dd47
--- /dev/null
+++ b/plugins/converter.py
@@ -0,0 +1,191 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_converter")
+
+import os
+import time
+
+from . import LOGS
+
+try:
+ import cv2
+except ImportError:
+ cv2 = None
+
+try:
+ from PIL import Image
+except ImportError:
+ LOGS.info(f"{__file__}: PIL not Installed.")
+ Image = None
+
+from telegraph import upload_file as uf
+
+from . import (
+ ULTConfig,
+ bash,
+ con,
+ downloader,
+ get_paste,
+ get_string,
+ udB,
+ ultroid_cmd,
+ uploader,
+)
+
+opn = []
+
+
+@ultroid_cmd(
+ pattern="thumbnail$",
+)
+async def _(e):
+ r = await e.get_reply_message()
+ if r.photo:
+ dl = await r.download_media()
+ elif r.document and r.document.thumbs:
+ dl = await r.download_media(thumb=-1)
+ else:
+ return await e.eor("`Reply to Photo or media with thumb...`")
+ variable = uf(dl)
+ os.remove(dl)
+ nn = f"https://graph.org{variable[0]}"
+ udB.set_key("CUSTOM_THUMBNAIL", str(nn))
+ await bash(f"wget {nn} -O resources/extras/ultroid.jpg")
+ await e.eor(get_string("cvt_6").format(nn), link_preview=False)
+
+
+@ultroid_cmd(
+ pattern="rename( (.*)|$)",
+)
+async def imak(event):
+ reply = await event.get_reply_message()
+ t = time.time()
+ if not reply:
+ return await event.eor(get_string("cvt_1"))
+ inp = event.pattern_match.group(1).strip()
+ if not inp:
+ return await event.eor(get_string("cvt_2"))
+ xx = await event.eor(get_string("com_1"))
+ if reply.media:
+ if hasattr(reply.media, "document"):
+ file = reply.media.document
+ image = await downloader(
+ reply.file.name or str(time.time()),
+ reply.media.document,
+ xx,
+ t,
+ get_string("com_5"),
+ )
+
+ file = image.name
+ else:
+ file = await event.client.download_media(reply.media)
+ if os.path.exists(inp):
+ os.remove(inp)
+ await bash(f'mv """{file}""" """{inp}"""')
+ if not os.path.exists(inp) or os.path.exists(inp) and not os.path.getsize(inp):
+ os.rename(file, inp)
+ k = time.time()
+ xxx = await uploader(inp, inp, k, xx, get_string("com_6"))
+ await event.reply(
+ f"`{xxx.name}`",
+ file=xxx,
+ force_document=True,
+ thumb=ULTConfig.thumb,
+ )
+ os.remove(inp)
+ await xx.delete()
+
+
+conv_keys = {
+ "img": "png",
+ "sticker": "webp",
+ "webp": "webp",
+ "image": "png",
+ "webm": "webm",
+ "gif": "gif",
+ "json": "json",
+ "tgs": "tgs",
+}
+
+
+@ultroid_cmd(
+ pattern="convert( (.*)|$)",
+)
+async def uconverter(event):
+ xx = await event.eor(get_string("com_1"))
+ a = await event.get_reply_message()
+ if a is None:
+ return await event.eor("`Reply to Photo or media with thumb...`")
+ input_ = event.pattern_match.group(1).strip()
+ b = await a.download_media("resources/downloads/")
+ if not b and (a.document and a.document.thumbs):
+ b = await a.download_media(thumb=-1)
+ if not b:
+ return await xx.edit(get_string("cvt_3"))
+ try:
+ convert = conv_keys[input_]
+ except KeyError:
+ return await xx.edit(get_string("sts_3").format("gif/img/sticker/webm"))
+ file = await con.convert(b, outname="ultroid", convert_to=convert)
+ if file:
+ await event.client.send_file(
+ event.chat_id, file, reply_to=event.reply_to_msg_id or event.id
+ )
+ os.remove(file)
+ await xx.delete()
+
+
+@ultroid_cmd(
+ pattern="doc( (.*)|$)",
+)
+async def _(event):
+ input_str = event.pattern_match.group(1).strip()
+ if not (input_str and event.is_reply):
+ return await event.eor(get_string("cvt_1"), time=5)
+ xx = await event.eor(get_string("com_1"))
+ a = await event.get_reply_message()
+ if not a.message:
+ return await xx.edit(get_string("ex_1"))
+ with open(input_str, "w") as b:
+ b.write(str(a.message))
+ await xx.edit(f"**Packing into** `{input_str}`")
+ await event.reply(file=input_str, thumb=ULTConfig.thumb)
+ await xx.delete()
+ os.remove(input_str)
+
+
+@ultroid_cmd(
+ pattern="open( (.*)|$)",
+)
+async def _(event):
+ a = await event.get_reply_message()
+ b = event.pattern_match.group(1).strip()
+ if not ((a and a.media) or (b and os.path.exists(b))):
+ return await event.eor(get_string("cvt_7"), time=5)
+ xx = await event.eor(get_string("com_1"))
+ rem = None
+ if not b:
+ b = await a.download_media()
+ rem = True
+ try:
+ with open(b) as c:
+ d = c.read()
+ except UnicodeDecodeError:
+ return await xx.eor(get_string("cvt_8"), time=5)
+ try:
+ await xx.edit(f"```{d}```")
+ except BaseException:
+ what, key = await get_paste(d)
+ await xx.edit(
+ f"**MESSAGE EXCEEDS TELEGRAM LIMITS**\n\nSo Pasted It On [SPACEBIN](https://spaceb.in/{key})"
+ )
+ if rem:
+ os.remove(b)
diff --git a/plugins/core.py b/plugins/core.py
new file mode 100644
index 0000000000000000000000000000000000000000..6664fa5800275464bee832f87e88a1b2238cc5e5
--- /dev/null
+++ b/plugins/core.py
@@ -0,0 +1,124 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+
+from . import get_help
+
+__doc__ = get_help("help_core")
+
+
+import os
+
+from pyUltroid.startup.loader import load_addons
+
+from . import LOGS, async_searcher, eod, get_string, safeinstall, ultroid_cmd, un_plug
+
+
+@ultroid_cmd(pattern="install", fullsudo=True)
+async def install(event):
+ await safeinstall(event)
+
+
+@ultroid_cmd(
+ pattern=r"unload( (.*)|$)",
+)
+async def unload(event):
+ shortname = event.pattern_match.group(1).strip()
+ if not shortname:
+ await event.eor(get_string("core_9"))
+ return
+ lsd = os.listdir("addons")
+ zym = f"{shortname}.py"
+ if zym in lsd:
+ try:
+ un_plug(shortname)
+ await event.eor(f"**Uɴʟᴏᴀᴅᴇᴅ** `{shortname}` **Sᴜᴄᴄᴇssғᴜʟʟʏ.**", time=3)
+ except Exception as ex:
+ LOGS.exception(ex)
+ return await event.eor(str(ex))
+ elif zym in os.listdir("plugins"):
+ return await event.eor(get_string("core_11"), time=3)
+ else:
+ await event.eor(f"**Nᴏ Pʟᴜɢɪɴ Nᴀᴍᴇᴅ** `{shortname}`", time=3)
+
+
+@ultroid_cmd(
+ pattern=r"uninstall( (.*)|$)",
+)
+async def uninstall(event):
+ shortname = event.pattern_match.group(1).strip()
+ if not shortname:
+ await event.eor(get_string("core_13"))
+ return
+ lsd = os.listdir("addons")
+ zym = f"{shortname}.py"
+ if zym in lsd:
+ try:
+ un_plug(shortname)
+ await event.eor(f"**Uɴɪɴsᴛᴀʟʟᴇᴅ** `{shortname}` **Sᴜᴄᴄᴇssғᴜʟʟʏ.**", time=3)
+ os.remove(f"addons/{shortname}.py")
+ except Exception as ex:
+ return await event.eor(str(ex))
+ elif zym in os.listdir("plugins"):
+ return await event.eor(get_string("core_15"), time=3)
+ else:
+ return await event.eor(f"**Nᴏ Pʟᴜɢɪɴ Nᴀᴍᴇᴅ** `{shortname}`", time=3)
+
+
+@ultroid_cmd(
+ pattern=r"load( (.*)|$)",
+ fullsudo=True,
+)
+async def load(event):
+ shortname = event.pattern_match.group(1).strip()
+ if not shortname:
+ await event.eor(get_string("core_16"))
+ return
+ try:
+ try:
+ un_plug(shortname)
+ except BaseException:
+ pass
+ load_addons(f"addons/{shortname}.py")
+ await event.eor(get_string("core_17").format(shortname), time=3)
+ except Exception as e:
+ LOGS.exception(e)
+ await eod(
+ event,
+ get_string("core_18").format(shortname, e),
+ time=3,
+ )
+
+
+@ultroid_cmd(pattern="getaddons( (.*)|$)", fullsudo=True)
+async def get_the_addons_lol(event):
+ thelink = event.pattern_match.group(1).strip()
+ xx = await event.eor(get_string("com_1"))
+ fool = get_string("gas_1")
+ if thelink is None:
+ return await xx.eor(fool, time=10)
+ split_thelink = thelink.split("/")
+ if not ("raw" in thelink and thelink.endswith(".py")):
+ return await xx.eor(fool, time=10)
+ name_of_it = split_thelink[-1]
+ plug = await async_searcher(thelink)
+ fil = f"addons/{name_of_it}"
+ await xx.edit("Packing the codes...")
+ with open(fil, "w", encoding="utf-8") as uult:
+ uult.write(plug)
+ await xx.edit("Packed. Now loading the plugin..")
+ shortname = name_of_it.split(".")[0]
+ try:
+ load_addons(fil)
+ await xx.eor(get_string("core_17").format(shortname), time=15)
+ except Exception as e:
+ LOGS.exception(e)
+ await eod(
+ xx,
+ get_string("core_18").format(shortname, e),
+ time=3,
+ )
diff --git a/plugins/database.py b/plugins/database.py
new file mode 100644
index 0000000000000000000000000000000000000000..8c50ea2a3a80b452217dfdfdeca18fa4ae380279
--- /dev/null
+++ b/plugins/database.py
@@ -0,0 +1,77 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+
+from . import get_help
+
+__doc__ = get_help("help_database")
+
+
+import re
+
+from . import Redis, eor, get_string, udB, ultroid_cmd
+
+
+@ultroid_cmd(pattern="setdb( (.*)|$)", fullsudo=True)
+async def _(ult):
+ match = ult.pattern_match.group(1).strip()
+ if not match:
+ return await ult.eor("Provide key and value to set!")
+ try:
+ delim = " " if re.search("[|]", match) is None else " | "
+ data = match.split(delim, maxsplit=1)
+ if data[0] in ["--extend", "-e"]:
+ data = data[1].split(maxsplit=1)
+ data[1] = f"{str(udB.get_key(data[0]))} {data[1]}"
+ udB.set_key(data[0], data[1])
+ await ult.eor(
+ f"**DB Key Value Pair Updated\nKey :** `{data[0]}`\n**Value :** `{data[1]}`"
+ )
+
+ except BaseException:
+ await ult.eor(get_string("com_7"))
+
+
+@ultroid_cmd(pattern="deldb( (.*)|$)", fullsudo=True)
+async def _(ult):
+ key = ult.pattern_match.group(1).strip()
+ if not key:
+ return await ult.eor("Give me a key name to delete!", time=5)
+ _ = key.split(maxsplit=1)
+ try:
+ if _[0] == "-m":
+ for key in _[1].split():
+ k = udB.del_key(key)
+ key = _[1]
+ else:
+ k = udB.del_key(key)
+ if k == 0:
+ return await ult.eor("`No Such Key.`")
+ await ult.eor(f"`Successfully deleted key {key}`")
+ except BaseException:
+ await ult.eor(get_string("com_7"))
+
+
+@ultroid_cmd(pattern="rendb( (.*)|$)", fullsudo=True)
+async def _(ult):
+ match = ult.pattern_match.group(1).strip()
+ if not match:
+ return await ult.eor("`Provide Keys name to rename..`")
+ delim = " " if re.search("[|]", match) is None else " | "
+ data = match.split(delim)
+ if Redis(data[0]):
+ try:
+ udB.rename(data[0], data[1])
+ await eor(
+ ult,
+ f"**DB Key Rename Successful\nOld Key :** `{data[0]}`\n**New Key :** `{data[1]}`",
+ )
+
+ except BaseException:
+ await ult.eor(get_string("com_7"))
+ else:
+ await ult.eor("Key not found")
diff --git a/plugins/dbx.py b/plugins/dbx.py
new file mode 100644
index 0000000000000000000000000000000000000000..970a5a0000b89ff68a54a4dc54dcd50a5d466b34
--- /dev/null
+++ b/plugins/dbx.py
@@ -0,0 +1,123 @@
+import dns.resolver
+import re
+
+from motor.motor_asyncio import AsyncIOMotorClient
+from telethon import errors
+
+from . import ultroid_cmd, LOGS, run_async
+
+dns.resolver.default_resolver = dns.resolver.Resolver(configure=False)
+dns.resolver.default_resolver.nameservers = ['8.8.8.8']
+
+MONGO_URI = "mongodb+srv://xannychef:GlZdS1tZ4CiKDrcN@vouchdb.elfcz.mongodb.net/?retryWrites=true&w=majority&appName=vouchdb"
+mongo_client = AsyncIOMotorClient(MONGO_URI)
+db = mongo_client['vouchdata']
+vouch_collection = db['vouches']
+
+BATCH_SIZE = 1000
+
+AUTHORIZED_USERS = [5575183435]
+
+@ultroid_cmd(pattern=r"dbx(?: |$)(.*)", allow_sudo=True)
+async def db_command_handler(event):
+ try:
+ args = event.pattern_match.group(1).split()
+ user_id = event.sender_id
+
+ if user_id not in AUTHORIZED_USERS:
+ await event.reply("❌ You are not authorized to use this command.")
+ return
+
+ if len(args) < 2:
+ await event.reply("❌ Invalid command. Usage:\n.db -index \n.db -update ")
+ return
+
+ command = args[0]
+ try:
+ channel_id = int(args[1])
+ except ValueError:
+ await event.reply("❌ Channel ID must be an integer.")
+ return
+
+ from_message_id = int(args[2]) if command == "-update" and len(args) > 2 else None
+
+ if command not in ["-index", "-update"]:
+ await event.reply("❌ Invalid flag. Use -index or -update.")
+ return
+
+ processing_msg = await event.reply("🔍 Starting to process messages from the channel...")
+
+ total_message_count = 0
+ batch_data = []
+ progress_update_interval = 10000
+
+ try:
+ channel = await event.client.get_entity(channel_id)
+ except errors.ChannelPrivateError:
+ await processing_msg.edit("❌ Cannot access the specified channel. It might be private or you lack permissions.")
+ return
+ except Exception as e:
+ await processing_msg.edit(f"❌ Error accessing the channel: {str(e)}")
+ return
+
+ try:
+ if command == "-index":
+ total_messages = (await event.client.get_messages(channel, limit=1)).total
+ await processing_msg.edit(f"🔍 Total messages to process: {total_messages}")
+
+ async for message in event.client.iter_messages(channel_id):
+ await process_message(message, batch_data, processing_msg, total_message_count, progress_update_interval)
+ total_message_count += 1
+
+ elif command == "-update":
+ if not from_message_id:
+ await processing_msg.edit("❌ For -update, you must provide a from_message_id.")
+ return
+
+ async for message in event.client.iter_messages(channel_id, min_id=from_message_id):
+ await process_message(message, batch_data, processing_msg, total_message_count, progress_update_interval)
+ total_message_count += 1
+
+ if batch_data:
+ await vouch_collection.insert_many(batch_data)
+ batch_data.clear()
+
+ await processing_msg.edit(f"✅ Completed {command[1:]}ing {total_message_count} messages.")
+ except Exception as e:
+ LOGS.error(f"Error during {command[1:]}ing: {str(e)}")
+ await processing_msg.edit(f"❌ Error during {command[1:]}ing: {str(e)}")
+ except Exception as e:
+ LOGS.error(f"Unexpected error: {str(e)}")
+ await event.reply(f"❌ An unexpected error occurred: {str(e)}")
+
+async def process_message(message, batch_data, processing_msg, total_message_count, progress_update_interval):
+ if message.sender and message.sender.username and message.sender.username.lower().endswith('bot'):
+ return
+
+ vouched_by = message.sender.username if message.sender else "Unknown"
+ description = message.message or "No description"
+ message_id = message.id
+
+ vouched_user_match = re.search(r"@\w+", description)
+ vouched_user = vouched_user_match.group(0) if vouched_user_match else "Unknown"
+
+ vouch_data = {
+ "vouched_by": vouched_by,
+ "description": description,
+ "vouched_user": vouched_user,
+ "message_id": message_id,
+ "channel_id": message.chat_id
+ }
+
+ existing_document = await vouch_collection.find_one({"message_id": message_id, "channel_id": message.chat_id})
+ if existing_document:
+ await vouch_collection.update_one({"_id": existing_document["_id"]}, {"$set": vouch_data})
+ else:
+ batch_data.append(vouch_data)
+
+ if len(batch_data) >= BATCH_SIZE:
+ await vouch_collection.insert_many(batch_data)
+ batch_data.clear()
+
+ if total_message_count and total_message_count % progress_update_interval == 0:
+ await processing_msg.edit(f"🔄 Processed {total_message_count} messages...")
\ No newline at end of file
diff --git a/plugins/devtools.py b/plugins/devtools.py
new file mode 100644
index 0000000000000000000000000000000000000000..bd773ba97c7245739d3db4fd169a54b6ff246856
--- /dev/null
+++ b/plugins/devtools.py
@@ -0,0 +1,404 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_devtools")
+
+import inspect
+import sys
+import traceback
+from io import BytesIO, StringIO
+from os import remove
+from pprint import pprint
+
+from telethon.utils import get_display_name
+
+from pyUltroid import _ignore_eval
+
+from . import *
+
+# Used for Formatting Eval Code, if installed
+try:
+ import black
+except ImportError:
+ black = None
+from random import choice
+
+try:
+ from yaml import safe_load
+except ImportError:
+ from pyUltroid.fns.tools import safe_load
+try:
+ from telegraph import upload_file as uf
+except ImportError:
+ uf = None
+from telethon.tl import functions
+
+fn = functions
+
+
+@ultroid_cmd(
+ pattern="sysinfo$",
+)
+async def _(e):
+ try:
+ remove("Dockerfile")
+ except Exception:
+ pass
+ xx = await e.eor(get_string("com_1"))
+ x, y = await bash("neofetch|sed 's/\x1B\\[[0-9;\\?]*[a-zA-Z]//g' >> neo.txt")
+ if y and y.endswith("NOT_FOUND"):
+ return await xx.edit(f"Error: `{y}`")
+ with open("neo.txt", "r", encoding="utf-8") as neo:
+ p = (neo.read()).replace("\n\n", "")
+ haa = await Carbon(code=p, file_name="neofetch", backgroundColor=choice(ATRA_COL))
+ if isinstance(haa, dict):
+ await xx.edit(f"`{haa}`")
+ else:
+ await e.reply(file=haa)
+ await xx.delete()
+ remove("neo.txt")
+
+
+@ultroid_cmd(pattern="bash", fullsudo=True, only_devs=True)
+async def _(event):
+ try:
+ remove("Dockerfile")
+ except Exception:
+ pass
+ carb, rayso, yamlf = None, None, False
+ try:
+ cmd = event.text.split(" ", maxsplit=1)[1]
+ if cmd.split()[0] in ["-c", "--carbon"]:
+ cmd = cmd.split(maxsplit=1)[1]
+ carb = True
+ if cmd.split()[0] in ["-r", "--rayso"]:
+ cmd = cmd.split(maxsplit=1)[1]
+ rayso = True
+ except IndexError:
+ return await event.eor(get_string("devs_1"), time=10)
+ xx = await event.eor(get_string("com_1"))
+ reply_to_id = event.reply_to_msg_id or event.id
+ stdout, stderr = await bash(cmd, run_code=1)
+ OUT = f"**[👩💻](emoji/5301083932211550593) Ⲃⲁⲋⲏ\n\n• COMMAND:**\n`{cmd}` \n\n"
+ err, out = "", ""
+ if stderr:
+ err = f"**[⚠️](emoji/5213205860498549992) Ⲉɴfⲟʀmⲁtⲓⲟɴ:** \n`{stderr}`\n\n"
+ if stdout:
+ if (carb or udB.get_key("CARBON_ON_BASH")) and (
+ event.is_private
+ or event.chat.admin_rights
+ or event.chat.creator
+ or event.chat.default_banned_rights.embed_links
+ ):
+ li = await Carbon(
+ code=stdout,
+ file_name="bash",
+ download=True,
+ backgroundColor=choice(ATRA_COL),
+ )
+ if isinstance(li, dict):
+ await xx.edit(
+ f"Unknown Response from Carbon: `{li}`\n\nstdout`:{stdout}`\nstderr: `{stderr}`"
+ )
+ return
+ url = f"https://graph.org{uf(li)[-1]}"
+ OUT = f"[\xad]({url}){OUT}"
+ out = f"**[👨💻](emoji/5319161050128459957) Ⲟυⲧⲣυⲧ:**"
+ remove(li)
+ elif (rayso or udB.get_key("RAYSO_ON_BASH")) and (
+ event.is_private
+ or event.chat.admin_rights
+ or event.chat.creator
+ or event.chat.default_banned_rights.embed_links
+ ):
+ li = await Carbon(
+ code=stdout,
+ file_name="bash",
+ download=True,
+ backgroundColor=choice(ATRA_COL),
+ rayso=True,
+ )
+ if isinstance(li, dict):
+ await xx.edit(
+ f"Unknown Response from Carbon: `{li}`\n\nstdout`:{stdout}`\nstderr: `{stderr}`"
+ )
+ return
+ url = f"https://graph.org{uf(li)[-1]}"
+ OUT = f"[\xad]({url}){OUT}"
+ out = f"**[👨💻](emoji/5319161050128459957) Ⲟυⲧⲣυⲧ:**"
+ remove(li)
+ else:
+ if "pip" in cmd and all(":" in line for line in stdout.split("\n")):
+ try:
+ load = safe_load(stdout)
+ stdout = ""
+ for data in list(load.keys()):
+ res = load[data] or ""
+ if res and "http" not in str(res):
+ res = f"`{res}`"
+ stdout += f"**{data}** : {res}\n"
+ yamlf = True
+ except Exception as er:
+ stdout = f"`{stdout}`"
+ LOGS.exception(er)
+ else:
+ stdout = f"`{stdout}`"
+ out = f"**[👨💻](emoji/5319161050128459957) Ⲟυⲧⲣυⲧ:**\n{stdout}"
+ if not stderr and not stdout:
+ out = f"**[👨💻](emoji/5319161050128459957) Ⲟυⲧⲣυⲧ:**\n`Ⲋυⲥⲥⲉⲋⲋ`"
+ OUT += err + out
+ if len(OUT) > 4096:
+ ultd = err + out
+ with BytesIO(str.encode(ultd)) as out_file:
+ out_file.name = "bash.txt"
+ await event.client.send_file(
+ event.chat_id,
+ out_file,
+ force_document=True,
+ thumb=ULTConfig.thumb,
+ allow_cache=False,
+ caption=f"`{cmd}`" if len(cmd) < 998 else None,
+ reply_to=reply_to_id,
+ )
+
+ await xx.delete()
+ else:
+ await xx.edit(OUT, link_preview=not yamlf)
+
+
+pp = pprint # ignore: pylint
+bot = ultroid = ultroid_bot
+
+
+class u:
+ _ = ""
+
+
+def _parse_eval(value=None):
+ if not value:
+ return value
+ if hasattr(value, "stringify"):
+ try:
+ return value.stringify()
+ except TypeError:
+ pass
+ elif isinstance(value, dict):
+ try:
+ return json_parser(value, indent=1)
+ except BaseException:
+ pass
+ elif isinstance(value, list):
+ newlist = "["
+ for index, child in enumerate(value):
+ newlist += "\n " + str(_parse_eval(child))
+ if index < len(value) - 1:
+ newlist += ","
+ newlist += "\n]"
+ return newlist
+ return str(value)
+
+
+@ultroid_cmd(pattern="eval", fullsudo=True, only_devs=True)
+async def _(event):
+ try:
+ remove("Dockerfile")
+ except Exception:
+ pass
+ try:
+ cmd = event.text.split(maxsplit=1)[1]
+ except IndexError:
+ return await event.eor(get_string("devs_2"), time=5)
+ xx = None
+ mode = ""
+ spli = cmd.split()
+
+ async def get_():
+ try:
+ cm = cmd.split(maxsplit=1)[1]
+ except IndexError:
+ await event.eor("->> Wrong Format <<-")
+ cm = None
+ return cm
+
+ if spli[0] in ["-s", "--silent"]:
+ await event.delete()
+ mode = "silent"
+ elif spli[0] in ["-n", "-noedit"]:
+ mode = "no-edit"
+ xx = await event.reply(get_string("com_1"))
+ elif spli[0] in ["-gs", "--source"]:
+ mode = "gsource"
+ elif spli[0] in ["-ga", "--args"]:
+ mode = "g-args"
+ if mode:
+ cmd = await get_()
+ if not cmd:
+ return
+ if mode != "silent" and not xx:
+ xx = await event.eor(get_string("com_1"))
+ if black:
+ try:
+ cmd = black.format_str(cmd, mode=black.Mode())
+ except BaseException:
+ # Consider it as Code Error, and move on to be shown ahead.
+ pass
+ reply_to_id = event.reply_to_msg_id or event
+ if (
+ any(item in cmd for item in KEEP_SAFE().All)
+ and not event.out
+ and event.sender_id != ultroid_bot.uid
+ ):
+ warning = await event.forward_to(udB.get_key("LOG_CHANNEL"))
+ await warning.reply(
+ f"Malicious Activities suspected by {inline_mention(await event.get_sender())}"
+ )
+ _ignore_eval.append(event.sender_id)
+ return await xx.edit(
+ f"`Malicious Activities suspected\nReported to owner. Aborted this request!`"
+ )
+ old_stderr = sys.stderr
+ old_stdout = sys.stdout
+ redirected_output = sys.stdout = StringIO()
+ redirected_error = sys.stderr = StringIO()
+ stdout, stderr, exc, timeg = None, None, None, None
+ tima = time.time()
+ try:
+ value = await aexec(cmd, event)
+ except Exception:
+ value = None
+ exc = traceback.format_exc()
+ tima = time.time() - tima
+ stdout = redirected_output.getvalue()
+ stderr = redirected_error.getvalue()
+ sys.stdout = old_stdout
+ sys.stderr = old_stderr
+ if value:
+ try:
+ if mode == "gsource":
+ exc = inspect.getsource(value)
+ elif mode == "g-args":
+ args = inspect.signature(value).parameters.values()
+ name = ""
+ if hasattr(value, "__name__"):
+ name = value.__name__
+ exc = f"**{name}**\n\n" + "\n ".join([str(arg) for arg in args])
+ except Exception:
+ exc = traceback.format_exc()
+ evaluation = exc or stderr or stdout or _parse_eval(value) or get_string("instu_4")
+ if mode == "silent":
+ if exc:
+ msg = f"[⚠️](emoji/5213205860498549992) EVAL Ⲉʀʀⲟʀ\n\n• CHAT: {get_display_name(event.chat)}
[{event.chat_id}
]"
+ msg += f"\n\n∆ CODE:\n{cmd}
\n\n∆ Ⲉʀʀⲟʀ:\n{exc}
"
+ log_chat = udB.get_key("LOG_CHANNEL")
+ if len(msg) > 4000:
+ with BytesIO(msg.encode()) as out_file:
+ out_file.name = "Eval-Error.txt"
+ return await event.client.send_message(
+ log_chat, f"`{cmd}`", file=out_file
+ )
+ await event.client.send_message(log_chat, msg, parse_mode="html")
+ return
+ tmt = tima * 1000
+ timef = time_formatter(tmt)
+ timeform = timef if timef != "0s" else f"{tmt:.3f}ms"
+ final_output = (
+ "{} **Ⲉⳳⲁⳑ** (__in {}__)\n```{}``` \n\n{} **Ⲟυⲧⲣυⲧ**: \n```{}``` \n".format(
+ f"[👩💻](emoji/5300928913956938544)",
+ timeform,
+ cmd,
+ f"[👨💻](emoji/5319161050128459957)",
+ evaluation,
+ )
+ )
+ if len(final_output) > 4096:
+ final_output = evaluation
+ with BytesIO(str.encode(final_output)) as out_file:
+ out_file.name = "eval.txt"
+ await event.client.send_file(
+ event.chat_id,
+ out_file,
+ force_document=True,
+ thumb=ULTConfig.thumb,
+ allow_cache=False,
+ caption=f"```{cmd}```" if len(cmd) < 998 else None,
+ reply_to=reply_to_id,
+ )
+ return await xx.delete()
+ await xx.edit(final_output)
+
+
+def _stringify(text=None, *args, **kwargs):
+ if text:
+ u._ = text
+ text = _parse_eval(text)
+ return print(text, *args, **kwargs)
+
+
+async def aexec(code, event):
+ exec(
+ (
+ "async def __aexec(e, client): "
+ + "\n print = p = _stringify"
+ + "\n message = event = e"
+ + "\n u.r = reply = await event.get_reply_message()"
+ + "\n chat = event.chat_id"
+ + "\n u.lr = locals()"
+ )
+ + "".join(f"\n {l}" for l in code.split("\n"))
+ )
+
+ return await locals()["__aexec"](event, event.client)
+
+
+DUMMY_CPP = """#include
+using namespace std;
+
+int main(){
+!code
+}
+"""
+
+
+@ultroid_cmd(pattern="cpp", only_devs=True)
+async def doie(e):
+ match = e.text.split(" ", maxsplit=1)
+ try:
+ match = match[1]
+ except IndexError:
+ return await e.eor(get_string("devs_3"))
+ msg = await e.eor(get_string("com_1"))
+ if "main(" not in match:
+ new_m = "".join(" " * 4 + i + "\n" for i in match.split("\n"))
+ match = DUMMY_CPP.replace("!code", new_m)
+ open("cpp-ultroid.cpp", "w").write(match)
+ m = await bash("g++ -o CppUltroid cpp-ultroid.cpp")
+ o_cpp = f"• **Eval-Cpp**\n`{match}`"
+ if m[1]:
+ o_cpp += f"\n\n**• Error :**\n`{m[1]}`"
+ if len(o_cpp) > 3000:
+ os.remove("cpp-ultroid.cpp")
+ if os.path.exists("CppUltroid"):
+ os.remove("CppUltroid")
+ with BytesIO(str.encode(o_cpp)) as out_file:
+ out_file.name = "error.txt"
+ return await msg.reply(f"`{match}`", file=out_file)
+ return await eor(msg, o_cpp)
+ m = await bash("./CppUltroid")
+ if m[0] != "":
+ o_cpp += f"\n\n**• Output :**\n`{m[0]}`"
+ if m[1]:
+ o_cpp += f"\n\n**• Error :**\n`{m[1]}`"
+ if len(o_cpp) > 3000:
+ with BytesIO(str.encode(o_cpp)) as out_file:
+ out_file.name = "eval.txt"
+ await msg.reply(f"`{match}`", file=out_file)
+ else:
+ await eor(msg, o_cpp)
+ os.remove("CppUltroid")
+ os.remove("cpp-ultroid.cpp")
diff --git a/plugins/downloadupload.py b/plugins/downloadupload.py
new file mode 100644
index 0000000000000000000000000000000000000000..003da9fad7ae8c7bd92c83f4c71a44b1b18a83d0
--- /dev/null
+++ b/plugins/downloadupload.py
@@ -0,0 +1,222 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_downloadupload")
+
+import asyncio
+import glob
+import os
+import time
+from datetime import datetime as dt
+
+from aiohttp.client_exceptions import InvalidURL
+from telethon.errors.rpcerrorlist import MessageNotModifiedError
+
+from pyUltroid.fns.helper import time_formatter
+from pyUltroid.fns.tools import get_chat_and_msgid, set_attributes
+
+from . import (
+ LOGS,
+ ULTConfig,
+ downloader,
+ eor,
+ fast_download,
+ get_all_files,
+ get_string,
+ progress,
+ time_formatter,
+ ultroid_cmd,
+)
+
+
+@ultroid_cmd(
+ pattern="download( (.*)|$)",
+)
+async def down(event):
+ matched = event.pattern_match.group(1).strip()
+ msg = await event.eor(get_string("udl_4"))
+ if not matched:
+ return await eor(msg, get_string("udl_5"), time=5)
+ try:
+ splited = matched.split(" | ")
+ link = splited[0]
+ filename = splited[1]
+ except IndexError:
+ filename = None
+ s_time = time.time()
+ try:
+ filename, d = await fast_download(
+ link,
+ filename,
+ progress_callback=lambda d, t: asyncio.get_event_loop().create_task(
+ progress(
+ d,
+ t,
+ msg,
+ s_time,
+ f"Downloading from {link}",
+ )
+ ),
+ )
+ except InvalidURL:
+ return await msg.eor("`Invalid URL provided :(`", time=5)
+ await msg.eor(f"`{filename}` `downloaded in {time_formatter(d*1000)}.`")
+
+
+@ultroid_cmd(
+ pattern="dl( (.*)|$)",
+)
+async def download(event):
+ match = event.pattern_match.group(1).strip()
+ if match and "t.me/" in match:
+ chat, msg = get_chat_and_msgid(match)
+ if not (chat and msg):
+ return await event.eor(get_string("gms_1"))
+ match = ""
+ ok = await event.client.get_messages(chat, ids=msg)
+ elif event.reply_to_msg_id:
+ ok = await event.get_reply_message()
+ else:
+ return await event.eor(get_string("cvt_3"), time=8)
+ xx = await event.eor(get_string("com_1"))
+ if not (ok and ok.media):
+ return await xx.eor(get_string("udl_1"), time=5)
+ s = dt.now()
+ k = time.time()
+ if hasattr(ok.media, "document"):
+ file = ok.media.document
+ mime_type = file.mime_type
+ filename = match or ok.file.name
+ if not filename:
+ if "audio" in mime_type:
+ filename = "audio_" + dt.now().isoformat("_", "seconds") + ".ogg"
+ elif "video" in mime_type:
+ filename = "video_" + dt.now().isoformat("_", "seconds") + ".mp4"
+ try:
+ result = await downloader(
+ f"resources/downloads/{filename}",
+ file,
+ xx,
+ k,
+ f"Downloading {filename}...",
+ )
+
+ except MessageNotModifiedError as err:
+ return await xx.edit(str(err))
+ file_name = result.name
+ else:
+ d = "resources/downloads/"
+ file_name = await event.client.download_media(
+ ok,
+ d,
+ progress_callback=lambda d, t: asyncio.get_event_loop().create_task(
+ progress(
+ d,
+ t,
+ xx,
+ k,
+ get_string("com_5"),
+ ),
+ ),
+ )
+ e = dt.now()
+ t = time_formatter(((e - s).seconds) * 1000)
+ await xx.eor(get_string("udl_2").format(file_name, t))
+
+
+@ultroid_cmd(
+ pattern="ul( (.*)|$)",
+)
+async def _(event):
+ msg = await event.eor(get_string("com_1"))
+ match = event.pattern_match.group(1)
+ if match:
+ match = match.strip()
+ if not event.out and match == ".env":
+ return await event.reply("`You can't do this...`")
+ stream, force_doc, delete, thumb = (
+ False,
+ True,
+ False,
+ ULTConfig.thumb,
+ )
+ if "--stream" in match:
+ stream = True
+ force_doc = False
+ if "--delete" in match:
+ delete = True
+ if "--no-thumb" in match:
+ thumb = None
+ arguments = ["--stream", "--delete", "--no-thumb"]
+ if any(item in match for item in arguments):
+ match = (
+ match.replace("--stream", "")
+ .replace("--delete", "")
+ .replace("--no-thumb", "")
+ .strip()
+ )
+ if match.endswith("/"):
+ match += "*"
+ results = glob.glob(match)
+ if not results and os.path.exists(match):
+ results = [match]
+ if not results:
+ try:
+ await event.reply(file=match)
+ return await event.try_delete()
+ except Exception as er:
+ LOGS.exception(er)
+ return await msg.eor(get_string("ls1"))
+ for result in results:
+ if os.path.isdir(result):
+ c, s = 0, 0
+ for files in get_all_files(result):
+ attributes = None
+ if stream:
+ try:
+ attributes = await set_attributes(files)
+ except KeyError as er:
+ LOGS.exception(er)
+ try:
+ file, _ = await event.client.fast_uploader(
+ files, show_progress=True, event=msg, to_delete=delete
+ )
+ await event.client.send_file(
+ event.chat_id,
+ file,
+ supports_streaming=stream,
+ force_document=force_doc,
+ thumb=thumb,
+ attributes=attributes,
+ caption=f"`Uploaded` `{files}` `in {time_formatter(_*1000)}`",
+ reply_to=event.reply_to_msg_id or event,
+ )
+ s += 1
+ except (ValueError, IsADirectoryError):
+ c += 1
+ break
+ attributes = None
+ if stream:
+ try:
+ attributes = await set_attributes(result)
+ except KeyError as er:
+ LOGS.exception(er)
+ file, _ = await event.client.fast_uploader(
+ result, show_progress=True, event=msg, to_delete=delete
+ )
+ await event.client.send_file(
+ event.chat_id,
+ file,
+ supports_streaming=stream,
+ force_document=force_doc,
+ thumb=thumb,
+ attributes=attributes,
+ caption=f"`Uploaded` `{result}` `in {time_formatter(_*1000)}`",
+ )
+ await msg.try_delete()
diff --git a/plugins/echo.py b/plugins/echo.py
new file mode 100644
index 0000000000000000000000000000000000000000..03c4d0e860a4988ec57111db09abb2216c0102b8
--- /dev/null
+++ b/plugins/echo.py
@@ -0,0 +1,76 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_echo")
+
+
+from telethon.utils import get_display_name
+
+from pyUltroid.dB.echo_db import add_echo, check_echo, list_echo, rem_echo
+
+from . import inline_mention, ultroid_cmd
+
+
+@ultroid_cmd(pattern="addecho( (.*)|$)")
+async def echo(e):
+ r = await e.get_reply_message()
+ if r:
+ user = r.sender_id
+ else:
+ try:
+ user = e.text.split()[1]
+ if user.startswith("@"):
+ ok = await e.client.get_entity(user)
+ user = ok.id
+ else:
+ user = int(user)
+ except BaseException:
+ return await e.eor("Reply To A user.", time=5)
+ if check_echo(e.chat_id, user):
+ return await e.eor("Echo already activated for this user.", time=5)
+ add_echo(e.chat_id, user)
+ ok = await e.client.get_entity(user)
+ user = inline_mention(ok)
+ await e.eor(f"Activated Echo For {user}.")
+
+
+@ultroid_cmd(pattern="remecho( (.*)|$)")
+async def rm(e):
+ r = await e.get_reply_message()
+ if r:
+ user = r.sender_id
+ else:
+ try:
+ user = e.text.split()[1]
+ if user.startswith("@"):
+ ok = await e.client.get_entity(user)
+ user = ok.id
+ else:
+ user = int(user)
+ except BaseException:
+ return await e.eor("Reply To A User.", time=5)
+ if check_echo(e.chat_id, user):
+ rem_echo(e.chat_id, user)
+ ok = await e.client.get_entity(user)
+ user = f"[{get_display_name(ok)}](tg://user?id={ok.id})"
+ return await e.eor(f"Deactivated Echo For {user}.")
+ await e.eor("Echo not activated for this user")
+
+
+@ultroid_cmd(pattern="listecho$")
+async def lstecho(e):
+ if k := list_echo(e.chat_id):
+ user = "**Activated Echo For Users:**\n\n"
+ for x in k:
+ ok = await e.client.get_entity(int(x))
+ kk = f"[{get_display_name(ok)}](tg://user?id={ok.id})"
+ user += f"•{kk}" + "\n"
+ await e.eor(user)
+ else:
+ await e.eor("`List is Empty, For echo`", time=5)
diff --git a/plugins/extra.py b/plugins/extra.py
new file mode 100644
index 0000000000000000000000000000000000000000..f9abda572addb4a676be73d4faf38abe6cb60bbc
--- /dev/null
+++ b/plugins/extra.py
@@ -0,0 +1,85 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("extra")
+
+import asyncio
+
+from . import get_string, ultroid_cmd
+
+
+@ultroid_cmd(
+ pattern="del$",
+ manager=True,
+)
+async def delete_it(delme):
+ msg_src = await delme.get_reply_message()
+ if not msg_src:
+ return
+ await msg_src.try_delete()
+ await delme.try_delete()
+
+
+@ultroid_cmd(
+ pattern="copy$",
+)
+async def copy(e):
+ reply = await e.get_reply_message()
+ if reply:
+ await reply.reply(reply)
+ return await e.try_delete()
+ await e.eor(get_string("ex_1"), time=5)
+
+
+@ultroid_cmd(
+ pattern="edit",
+)
+async def editer(edit):
+ message = edit.text
+ chat = await edit.get_input_chat()
+ string = str(message[6:])
+ reply = await edit.get_reply_message()
+ if reply and reply.text:
+ try:
+ await reply.edit(string)
+ await edit.delete()
+ except BaseException:
+ pass
+ else:
+ i = 1
+ async for message in edit.client.iter_messages(chat, from_user="me", limit=2):
+ if i == 2:
+ await message.edit(string)
+ await edit.delete()
+ break
+ i += 1
+
+
+@ultroid_cmd(
+ pattern="reply$",
+)
+async def _(e):
+ if e.reply_to_msg_id:
+ chat = e.chat_id
+ try:
+ msg = (await e.client.get_messages(e.chat_id, limit=1, max_id=e.id))[0]
+ except IndexError:
+ return await e.eor(
+ "`You have previously sent no message to reply again...`", time=5
+ )
+ except BaseException as er:
+ return await e.eor(f"**ERROR:** `{er}`")
+ await asyncio.wait(
+ [
+ e.client.delete_messages(chat, [e.id, msg.id]),
+ e.client.send_message(chat, msg, reply_to=e.reply_to_msg_id),
+ ]
+ )
+ else:
+ await e.try_delete()
diff --git a/plugins/fakeaction.py b/plugins/fakeaction.py
new file mode 100644
index 0000000000000000000000000000000000000000..0f4b25492e2c4b9afbae3f6972dd400f2acf504a
--- /dev/null
+++ b/plugins/fakeaction.py
@@ -0,0 +1,36 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_fakeaction")
+
+import math
+import time
+
+from pyUltroid.fns.admins import ban_time
+
+from . import asyncio, get_string, ultroid_cmd
+
+
+@ultroid_cmd(
+ pattern="f(typing|audio|contact|document|game|location|sticker|photo|round|video)( (.*)|$)"
+)
+async def _(e):
+ act = e.pattern_match.group(1).strip()
+ t = e.pattern_match.group(2)
+ if act in ["audio", "round", "video"]:
+ act = f"record-{act}"
+ if t.isdigit():
+ t = int(t)
+ elif t.endswith(("s", "h", "d", "m")):
+ t = math.ceil((ban_time(t)) - time.time())
+ else:
+ t = 60
+ await e.eor(get_string("fka_1").format(str(t)), time=5)
+ async with e.client.action(e.chat_id, act):
+ await asyncio.sleep(t)
diff --git a/plugins/fileshare.py b/plugins/fileshare.py
new file mode 100644
index 0000000000000000000000000000000000000000..430e8cd5beddec9e679000014085639e3926bf29
--- /dev/null
+++ b/plugins/fileshare.py
@@ -0,0 +1,95 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_fileshare")
+
+import os
+
+from pyUltroid.dB.filestore_db import del_stored, get_stored_msg, list_all_stored_msgs
+from pyUltroid.fns.tools import get_file_link
+
+from . import HNDLR, asst, get_string, in_pattern, udB, ultroid_bot, ultroid_cmd
+
+
+@ultroid_cmd(pattern="store$")
+async def filestoreplg(event):
+ msg = await event.get_reply_message()
+ if not msg:
+ return await event.eor(get_string("fsh_3"), time=10)
+ # allow storing both messages and media.
+ filehash = await get_file_link(msg)
+ link_to_file = f"https://t.me/{asst.me.username}?start={filehash}"
+ await event.eor(
+ get_string("fsh_2").format(link_to_file),
+ link_preview=False,
+ )
+
+
+@ultroid_cmd("delstored ?(.*)")
+async def _(event):
+ match = event.pattern_match.group(1)
+ if not match:
+ return await event.eor("`Give stored film's link to delete.`", time=5)
+ match = match.split("?start=")
+ botusername = match[0].split("/")[-1]
+ if botusername != asst.me.username:
+ return await event.eor(
+ "`Message/Media of provided link was not stored by this bot.`", time=5
+ )
+ msg_id = get_stored_msg(match[1])
+ if not msg_id:
+ return await event.eor(
+ "`Message/Media of provided link was already deleted.`", time=5
+ )
+ del_stored(match[1])
+ await ultroid_bot.delete_messages(udB.get_key("LOG_CHANNEL"), int(msg_id))
+ await event.eor("__Deleted__")
+
+
+@ultroid_cmd("liststored$")
+async def liststored(event):
+ files = list_all_stored_msgs()
+ if not files:
+ return await event.eor(get_string("fsh_4"), time=5)
+ msg = "**Stored files:**\n"
+ for c, i in enumerate(files, start=1):
+ msg += f"`{c}`. https://t.me/{asst.me.username}?start={i}\n"
+ if len(msg) > 4095:
+ with open("liststored.txt", "w") as f:
+ f.write(msg.replace("**", "").replace("`", ""))
+ await event.reply(get_string("fsh_1"), file="liststored.txt")
+ os.remove("liststored.txt")
+ return
+ await event.eor(msg, link_preview=False)
+
+
+@in_pattern("filestore", owner=True)
+async def file_short(event):
+ all_ = list_all_stored_msgs()
+ res = []
+ if all_:
+ LOG_CHA = udB.get_key("LOG_CHANNEL")
+ for msg in all_[:50]:
+ m_id = get_stored_msg(msg)
+ if not m_id:
+ continue
+ message = await asst.get_messages(LOG_CHA, ids=m_id)
+ if not message:
+ continue
+ if message.media:
+ res.append(await event.builder.document(title=msg, file=message.media))
+ elif message.text:
+ res.append(
+ await event.builder.article(title=message.text, text=message.text)
+ )
+ if not res:
+ title = "You have no stored file :("
+ text = f"{title}\n\nRead `{HNDLR}help fileshare` to know how to store."
+ return await event.answer([await event.builder.article(title=title, text=text)])
+ await event.answer(res, switch_pm="• File Store •", switch_pm_param="start")
diff --git a/plugins/filter.py b/plugins/filter.py
new file mode 100644
index 0000000000000000000000000000000000000000..84ab5931efb3e1d9c9ee359f52483ae45f6a5731
--- /dev/null
+++ b/plugins/filter.py
@@ -0,0 +1,102 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_filter")
+
+import os
+import re
+
+from telegraph import upload_file as uf
+from telethon.tl.types import User
+from telethon.utils import pack_bot_file_id
+
+from pyUltroid.dB.filter_db import add_filter, get_filter, list_filter, rem_filter
+from pyUltroid.fns.tools import create_tl_btn, format_btn, get_msg_button
+
+from . import events, get_string, mediainfo, udB, ultroid_bot, ultroid_cmd
+from ._inline import something
+
+
+@ultroid_cmd(pattern="addfilter( (.*)|$)")
+async def af(e):
+ wrd = (e.pattern_match.group(1).strip()).lower()
+ wt = await e.get_reply_message()
+ chat = e.chat_id
+ if not (wt and wrd):
+ return await e.eor(get_string("flr_1"))
+ btn = format_btn(wt.buttons) if wt.buttons else None
+ if wt and wt.media:
+ wut = mediainfo(wt.media)
+ if wut.startswith(("pic", "gif")):
+ dl = await wt.download_media()
+ variable = uf(dl)
+ m = f"https://graph.org{variable[0]}"
+ elif wut == "video":
+ if wt.media.document.size > 8 * 1000 * 1000:
+ return await e.eor(get_string("com_4"), time=5)
+ dl = await wt.download_media()
+ variable = uf(dl)
+ os.remove(dl)
+ m = f"https://graph.org{variable[0]}"
+ else:
+ m = pack_bot_file_id(wt.media)
+ if wt.text:
+ txt = wt.text
+ if not btn:
+ txt, btn = get_msg_button(wt.text)
+ add_filter(chat, wrd, txt, m, btn)
+ else:
+ add_filter(chat, wrd, None, m, btn)
+ else:
+ txt = wt.text
+ if not btn:
+ txt, btn = get_msg_button(wt.text)
+ add_filter(chat, wrd, txt, None, btn)
+ await e.eor(get_string("flr_4").format(wrd))
+ ultroid_bot.add_handler(filter_func, events.NewMessage())
+
+
+@ultroid_cmd(pattern="remfilter( (.*)|$)")
+async def rf(e):
+ wrd = (e.pattern_match.group(1).strip()).lower()
+ chat = e.chat_id
+ if not wrd:
+ return await e.eor(get_string("flr_3"))
+ rem_filter(int(chat), wrd)
+ await e.eor(get_string("flr_5").format(wrd))
+
+
+@ultroid_cmd(pattern="listfilter$")
+async def lsnote(e):
+ if x := list_filter(e.chat_id):
+ sd = "Filters Found In This Chats Are\n\n"
+ return await e.eor(sd + x)
+ await e.eor(get_string("flr_6"))
+
+
+async def filter_func(e):
+ if isinstance(e.sender, User) and e.sender.bot:
+ return
+ xx = (e.text).lower()
+ chat = e.chat_id
+ if x := get_filter(chat):
+ for c in x:
+ pat = r"( |^|[^\w])" + re.escape(c) + r"( |$|[^\w])"
+ if re.search(pat, xx):
+ if k := x.get(c):
+ msg = k["msg"]
+ media = k["media"]
+ if k.get("button"):
+ btn = create_tl_btn(k["button"])
+ return await something(e, msg, media, btn)
+ await e.reply(msg, file=media)
+
+
+if udB.get_key("FILTERS"):
+ ultroid_bot.add_handler(filter_func, events.NewMessage())
diff --git a/plugins/flux2.py b/plugins/flux2.py
new file mode 100644
index 0000000000000000000000000000000000000000..8aded2e5955ecf309c1a03e8dc132c2ac98664d3
--- /dev/null
+++ b/plugins/flux2.py
@@ -0,0 +1,95 @@
+import requests
+import os
+import json
+from . import ultroid_cmd, LOGS, fast_download
+
+@ultroid_cmd(pattern="flux2(?:\s+(-p1|-p2|-l1|-l2|-s1|-s2|-hd)\s+(.*))?$")
+async def codegen(e):
+ # Default to "portrait_16_9" if no specific command is provided
+ args = e.pattern_match.group(2)
+ size_option = e.pattern_match.group(1) or "portrait_16_9"
+
+ # Map the size_option to the corresponding image size
+ size_mapping = {
+ "-p1": "portrait_4_3",
+ "-p2": "portrait_16_9",
+ "-l1": "landscape_4_3",
+ "-l2": "landscape_16_9",
+ "-s1": "square",
+ "-s2": "square_hd",
+ "-hd": "square_hd"
+ }
+ image_size = size_mapping.get(size_option, "portrait_16_9")
+
+ # Handle when no prompt is provided
+ if not args:
+ reply = await e.get_reply_message()
+ if reply and reply.text:
+ args = reply.text
+ if not args:
+ return await e.eor("Please provide a prompt to generate images.")
+
+ # Prepare the request
+ API_URL = "http://fal.run/fal-ai/flux/schnell"
+ headers = {
+ "user-agent": "Python/3.x",
+ "content-type": "application/json; charset=utf-8",
+ "accept-encoding": "gzip",
+ "authorization": "Key f2438e21-b687-46c3-998f-0ed0deed8778:6a073a3d9bb73a9ed1c7aa8e8d905ced"
+ }
+ data = {
+ "prompt": args,
+ "image_size": image_size,
+ "num_inference_steps": 4,
+ "num_images": 4,
+ "embeddings": [],
+ "format": "jpeg",
+ "sync_mode": False,
+ "seed": "0",
+ "enable_safety_checker": False
+ }
+
+ # Notify the user that image generation is in progress
+ moi = await e.eor("🔄 Generating images, please wait...")
+
+ try:
+ response = requests.post(API_URL, headers=headers, json=data)
+
+ if response.status_code != 200:
+ LOGS.error(f"Request failed with status code {response.status_code}")
+ return await moi.edit("Failed to generate images. Please try again later.")
+
+ images = response.json().get("images", [])
+ if not images:
+ return await moi.edit("No images were generated.")
+
+ # Download images
+ image_paths = await download_images([img["url"] for img in images])
+
+ # Send images as a group
+ await send_images_as_group(e, args, image_paths)
+
+ # Clean up the files after sending
+ for path in image_paths:
+ os.remove(path)
+
+ await moi.delete()
+
+ except Exception as exc:
+ LOGS.error(f"Error: {exc}")
+ await moi.edit(f"An error occurred: {exc}")
+
+async def download_images(image_urls):
+ downloaded_paths = []
+ for i, url in enumerate(image_urls, start=1):
+ filename = f"image_{i}.png"
+ path, _ = await fast_download(url, filename=filename)
+ downloaded_paths.append(path)
+ return downloaded_paths
+
+async def send_images_as_group(e, query, image_paths):
+ caption = f"^^{query}^^"
+ media = [await e.client.upload_file(path) for path in image_paths]
+ await e.client.send_message(
+ e.chat_id, caption, file=media, parse_mode="markdown", reply_to=e.reply_to_msg_id
+ )
\ No newline at end of file
diff --git a/plugins/fontgen.py b/plugins/fontgen.py
new file mode 100644
index 0000000000000000000000000000000000000000..1cce172bef98b71597fbf085ce14ae1df696ac28
--- /dev/null
+++ b/plugins/fontgen.py
@@ -0,0 +1,60 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+
+from . import get_help
+
+__doc__ = get_help("help_fontgen")
+
+import string
+
+from . import eod, ultroid_cmd
+
+_default = string.ascii_letters
+Fonts = {
+ "small caps": "ᴀʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘϙʀsᴛᴜᴠᴡxʏᴢABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ "monospace": "𝚊𝚋𝚌𝚍𝚎𝚏𝚐𝚑𝚒𝚓𝚔𝚕𝚖𝚗𝚘𝚙𝚚𝚛𝚜𝚝𝚞𝚟𝚠𝚡𝚢𝚣𝙰𝙱𝙲𝙳𝙴𝙵𝙶𝙷𝙸𝙹𝙺𝙻𝙼𝙽𝙾𝙿𝚀𝚁𝚂𝚃𝚄𝚅𝚆𝚇𝚈𝚉",
+ "double stroke": "𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫𝔸𝔹ℂ𝔻𝔼𝔽𝔾ℍ𝕀𝕁𝕂𝕃𝕄ℕ𝕆ℙℚℝ𝕊𝕋𝕌𝕍𝕎𝕏𝕐ℤ",
+ "script royal": "𝒶𝒷𝒸𝒹𝑒𝒻𝑔𝒽𝒾𝒿𝓀𝓁𝓂𝓃𝑜𝓅𝓆𝓇𝓈𝓉𝓊𝓋𝓌𝓍𝓎𝓏𝒜ℬ𝒞𝒟ℰℱ𝒢ℋℐ𝒥𝒦ℒℳ𝒩𝒪𝒫𝒬ℛ𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵",
+}
+
+
+@ultroid_cmd(
+ pattern="font( (.*)|$)",
+)
+async def _(e):
+ input = e.pattern_match.group(1).strip()
+ reply = await e.get_reply_message()
+ if not input:
+ m = "**Available Fonts**\n\n"
+ for x in Fonts.keys():
+ m += f"• `{x}`\n"
+ return await e.eor(m, time=5)
+ if not reply:
+ try:
+ _ = input.split(":", maxsplit=1)
+ font = _[0][:-1]
+ text = _[1]
+ except IndexError:
+ return await eod(e, help)
+ elif not input:
+ return await eod(e, "`Give font dude :/`")
+ else:
+ font = input
+ text = reply.message
+ if font not in Fonts.keys():
+ return await e.eor(f"`{font} not in font list`.", time=5)
+ msg = gen_font(text, Fonts[font])
+ await e.eor(msg)
+
+
+def gen_font(text, new_font):
+ new_font = " ".join(new_font).split()
+ for q in text:
+ if q in _default:
+ new = new_font[_default.index(q)]
+ text = text.replace(q, new)
+ return text
diff --git a/plugins/forcesubscribe.py b/plugins/forcesubscribe.py
new file mode 100644
index 0000000000000000000000000000000000000000..9804b28687bd4f6082783323a8aab989300e9ff4
--- /dev/null
+++ b/plugins/forcesubscribe.py
@@ -0,0 +1,179 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+"""
+✘ Commands Available -
+
+• `{i}fsub `
+ Enable ForceSub in Used Chat !
+
+• `{i}checkfsub`
+ Check/Get Active ForceSub Setting of Used Chat.
+
+• `{i}remfsub`
+ Remove ForceSub from Used Chat !
+
+ Note - You Need to be Admin in Both Channel/Chats
+ in order to Use ForceSubscribe.
+"""
+
+import re
+
+from telethon.errors.rpcerrorlist import ChatAdminRequiredError, UserNotParticipantError
+from telethon.tl.custom import Button
+from telethon.tl.functions.channels import GetParticipantRequest
+from telethon.tl.functions.messages import ExportChatInviteRequest
+from telethon.tl.types import (
+ Channel,
+ ChannelParticipantBanned,
+ ChannelParticipantLeft,
+ User,
+)
+
+from pyUltroid.dB.forcesub_db import add_forcesub, get_forcesetting, rem_forcesub
+
+from . import (
+ LOGS,
+ asst,
+ callback,
+ events,
+ get_string,
+ in_pattern,
+ inline_mention,
+ udB,
+ ultroid_bot,
+ ultroid_cmd,
+)
+
+CACHE = {}
+
+
+@ultroid_cmd(pattern="fsub( (.*)|$)", admins_only=True, groups_only=True)
+async def addfor(e):
+ match = e.pattern_match.group(1).strip()
+ if not match:
+ return await e.eor(get_string("fsub_1"), time=5)
+ try:
+ match = await e.client.parse_id(match)
+ except BaseException:
+ return await e.eor(get_string("fsub_2"), time=5)
+ add_forcesub(e.chat_id, match)
+ await e.eor("Added ForceSub in This Chat !")
+ ultroid_bot.add_handler(force_sub, events.NewMessage(incoming=True))
+
+
+@ultroid_cmd(pattern="remfsub$")
+async def remor(e):
+ res = rem_forcesub(e.chat_id)
+ if not res:
+ return await e.eor(get_string("fsub_3"), time=5)
+ await e.eor("Removed ForceSub...")
+
+
+@ultroid_cmd(pattern="checkfsub$")
+async def getfsr(e):
+ res = get_forcesetting(e.chat_id)
+ if not res:
+ return await e.eor("ForceSub is Not Active In This Chat !", time=5)
+ cha = await e.client.get_entity(int(res))
+ await e.eor(f"**ForceSub Status** : `Active`\n- **{cha.title}** `({res})`")
+
+
+@in_pattern("fsub( (.*)|$)", owner=True)
+async def fcall(e):
+ match = e.pattern_match.group(1).strip()
+ spli = match.split("_")
+ user = await ultroid_bot.get_entity(int(spli[0]))
+ cl = await ultroid_bot.get_entity(int(spli[1]))
+ text = f"Hi {inline_mention(user)}, You Need to Join"
+ text += f" {cl.title} in order to Chat in this Group."
+ el = (
+ f"https://t.me/{cl.username}"
+ if cl.username
+ else (await ultroid_bot(ExportChatInviteRequest(cl))).link
+ )
+
+ res = [
+ await e.builder.article(
+ title="forcesub",
+ text=text,
+ buttons=[
+ [Button.url(text=get_string("fsub_4"), url=el)],
+ [Button.inline(get_string("fsub_5"), data=f"unm_{match}")],
+ ],
+ )
+ ]
+ await e.answer(res)
+
+
+@callback(re.compile("unm_(.*)"))
+async def diesoon(e):
+ match = (e.data_match.group(1)).decode("UTF-8")
+ spli = match.split("_")
+ if e.sender_id != int(spli[0]):
+ return await e.answer(get_string("fsub_7"), alert=True)
+ try:
+ values = await ultroid_bot(GetParticipantRequest(int(spli[1]), int(spli[0])))
+ if isinstance(values.participant, ChannelParticipantLeft) or (
+ isinstance(values.participant, ChannelParticipantBanned) and values.left
+ ):
+ raise UserNotParticipantError("")
+ except UserNotParticipantError:
+ return await e.answer(
+ "Please Join That Channel !\nThen Click This Button !", alert=True
+ )
+ await ultroid_bot.edit_permissions(
+ e.chat_id, int(spli[0]), send_messages=True, until_date=None
+ )
+ await e.edit(get_string("fsub_8"))
+
+
+async def force_sub(ult):
+ if not udB.get_key("FORCESUB"):
+ return
+ user = await ult.get_sender()
+ joinchat = get_forcesetting(ult.chat_id)
+ if (not joinchat) or (isinstance(user, User) and user.bot):
+ return
+ if CACHE.get(ult.chat_id):
+ if CACHE[ult.chat_id].get(user.id):
+ CACHE[ult.chat_id].update({user.id: CACHE[ult.chat_id][user.id] + 1})
+ else:
+ CACHE[ult.chat_id].update({user.id: 1})
+ else:
+ CACHE.update({ult.chat_id: {user.id: 1}})
+ count = CACHE[ult.chat_id][user.id]
+ if count == 11:
+ CACHE[ult.chat_id][user.id] = 1
+ return
+ if count in range(2, 11):
+ return
+ try:
+ await ultroid_bot.get_permissions(int(joinchat), user.id)
+ return
+ except UserNotParticipantError:
+ pass
+ if isinstance(user, Channel):
+ try:
+ await ultroid_bot.edit_permissions(
+ ult.chat_id, user.id, view_messages=False
+ )
+ return
+ except BaseException as er:
+ LOGS.exception(er)
+ try:
+ await ultroid_bot.edit_permissions(ult.chat_id, user.id, send_messages=False)
+ except ChatAdminRequiredError:
+ return
+ except Exception as e:
+ await ult.delete()
+ LOGS.info(e)
+ res = await ultroid_bot.inline_query(asst.me.username, f"fsub {user.id}_{joinchat}")
+ await res[0].click(ult.chat_id, reply_to=ult.id)
+
+
+if udB.get_key("FORCESUB"):
+ ultroid_bot.add_handler(force_sub, events.NewMessage(incoming=True))
diff --git a/plugins/gdrive.py b/plugins/gdrive.py
new file mode 100644
index 0000000000000000000000000000000000000000..fbadce676830ef2d2b582eed78f7646c572dd606
--- /dev/null
+++ b/plugins/gdrive.py
@@ -0,0 +1,232 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+"""
+✘ Commands Available
+
+• `{i}gdul `
+ Reply to file to upload on Google Drive.
+ Add file name to upload on Google Drive.
+
+• `{i}gdown | `
+ Download from Gdrive link or file id.
+
+• `{i}gdsearch `
+ Search file name on Google Drive and get link.
+
+• `{i}gdlist`
+ List all GDrive files.
+
+• `{i}gdfolder`
+ Link to your Google Drive Folder.
+ If added then all files will be uploaded in this folder.
+"""
+
+import os
+import time
+
+from telethon.tl.types import Message
+
+from pyUltroid.fns.gDrive import GDriveManager
+from pyUltroid.fns.helper import time_formatter
+
+from . import ULTConfig, asst, eod, eor, get_string, ultroid_cmd
+
+
+@ultroid_cmd(
+ pattern="gdown( (.*)|$)",
+ fullsudo=True,
+)
+async def gdown(event):
+ GDrive = GDriveManager()
+ match = event.pattern_match.group(1).strip()
+ if not match:
+ return await eod(event, "`Give file id or Gdrive link to download from!`")
+ filename = match.split(" | ")[1].strip() if " | " in match else None
+ eve = await event.eor(get_string("com_1"))
+ _start = time.time()
+ status, response = await GDrive._download_file(eve, match, filename)
+ if not status:
+ return await eve.edit(response)
+ await eve.edit(
+ f"`Downloaded ``{response}`` in {time_formatter((time.time() - _start)*1000)}`"
+ )
+
+
+@ultroid_cmd(
+ pattern="gdlist$",
+ fullsudo=True,
+)
+async def files(event):
+ GDrive = GDriveManager()
+ if not os.path.exists(GDrive.token_file):
+ return await event.eor(get_string("gdrive_6").format(asst.me.username))
+ eve = await event.eor(get_string("com_1"))
+ msg = ""
+ if files := GDrive._list_files:
+ msg += f"{len(files.keys())} files found in gdrive.\n\n"
+ for _ in files:
+ msg += f"> [{files[_]}]({_})\n"
+ else:
+ msg += "Nothing in Gdrive"
+ if len(msg) < 4096:
+ await eve.edit(msg, link_preview=False)
+ else:
+ with open("drive-files.txt", "w") as f:
+ f.write(
+ msg.replace("[", "File Name: ")
+ .replace("](", "\n» Link: ")
+ .replace(")\n", "\n\n")
+ )
+ try:
+ await eve.delete()
+ except BaseException:
+ pass
+ await event.client.send_file(
+ event.chat_id,
+ "drive-files.txt",
+ thumb=ULTConfig.thumb,
+ reply_to=event,
+ )
+ os.remove("drive-files.txt")
+
+
+@ultroid_cmd(
+ pattern="gdul( (.*)|$)",
+ fullsudo=True,
+)
+async def _(event):
+ GDrive = GDriveManager()
+ if not os.path.exists(GDrive.token_file):
+ return await eod(event, get_string("gdrive_6").format(asst.me.username))
+ input_file = event.pattern_match.group(1).strip() or await event.get_reply_message()
+ if not input_file:
+ return await eod(event, "`Reply to file or give its location.`")
+ mone = await event.eor(get_string("com_1"))
+ if isinstance(input_file, Message):
+ location = "resources/downloads"
+ if input_file.photo:
+ filename = await input_file.download_media(location)
+ else:
+ filename = input_file.file.name
+ if not filename:
+ filename = str(round(time.time()))
+ filename = f"{location}/{filename}"
+ try:
+ filename, downloaded_in = await event.client.fast_downloader(
+ file=input_file.media.document,
+ filename=filename,
+ show_progress=True,
+ event=mone,
+ message=get_string("com_5"),
+ )
+ filename = filename.name
+ except Exception as e:
+ return await eor(mone, str(e), time=10)
+ await mone.edit(
+ f"`Downloaded to ``{filename}`.`",
+ )
+ else:
+ filename = input_file.strip()
+ if not os.path.exists(filename):
+ return await eod(
+ mone,
+ "File Not found in local server. Give me a file path :((",
+ time=5,
+ )
+ folder_id = None
+ if os.path.isdir(filename):
+ files = os.listdir(filename)
+ if not files:
+ return await eod(
+ mone, "`Requested directory is empty. Can't create empty directory.`"
+ )
+ folder_id = GDrive.create_directory(filename)
+ c = 0
+ for files in sorted(files):
+ file = f"{filename}/{files}"
+ if not os.path.isdir(file):
+ try:
+ await GDrive._upload_file(mone, path=file, folder_id=folder_id)
+ c += 1
+ except Exception as e:
+ return await mone.edit(
+ f"Exception occurred while uploading to gDrive {e}"
+ )
+ return await mone.edit(
+ f"`Uploaded `[{filename}](https://drive.google.com/folderview?id={folder_id})` with {c} files.`"
+ )
+ try:
+ g_drive_link = await GDrive._upload_file(
+ mone,
+ filename,
+ )
+ await mone.edit(
+ get_string("gdrive_7").format(filename.split("/")[-1], g_drive_link)
+ )
+ except Exception as e:
+ await mone.edit(f"Exception occurred while uploading to gDrive {e}")
+
+
+@ultroid_cmd(
+ pattern="gdsearch( (.*)|$)",
+ fullsudo=True,
+)
+async def _(event):
+ GDrive = GDriveManager()
+ if not os.path.exists(GDrive.token_file):
+ return await event.eor(get_string("gdrive_6").format(asst.me.username))
+ input_str = event.pattern_match.group(1).strip()
+ if not input_str:
+ return await event.eor("`Give filename to search on GDrive...`")
+ eve = await event.eor(f"`Searching for {input_str} in G-Drive...`")
+ files = GDrive.search(input_str)
+ msg = ""
+ if files:
+ msg += (
+ f"{len(files.keys())} files with {input_str} in title found in GDrive.\n\n"
+ )
+ for _ in files:
+ msg += f"> [{files[_]}]({_})\n"
+ else:
+ msg += f"`No files with title {input_str}`"
+ if len(msg) < 4096:
+ await eve.eor(msg, link_preview=False)
+ else:
+ with open("drive-files.txt", "w") as f:
+ f.write(
+ msg.replace("[", "File Name: ")
+ .replace("](", "\n» Link: ")
+ .replace(")\n", "\n\n")
+ )
+ try:
+ await eve.delete()
+ except BaseException:
+ pass
+ await event.client.send_file(
+ event.chat_id,
+ f"{input_str}.txt",
+ thumb=ULTConfig.thumb,
+ reply_to=event,
+ )
+ os.remove(f"{input_str}.txt")
+
+
+@ultroid_cmd(
+ pattern="gdfolder$",
+ fullsudo=True,
+)
+async def _(event):
+ GDrive = GDriveManager()
+ if not os.path.exists(GDrive.token_file):
+ return await event.eor(get_string("gdrive_6").format(asst.me.username))
+ if GDrive.folder_id:
+ await event.eor(
+ "`Your G-Drive Folder link : `\n"
+ + GDrive._create_folder_link(GDrive.folder_id)
+ )
+ else:
+ await eod(event, "Set FOLDERID from your Assistant bot's Settings ")
diff --git a/plugins/gemi.py b/plugins/gemi.py
new file mode 100644
index 0000000000000000000000000000000000000000..876302a6b7af85edfe0a647d956354184ace472a
--- /dev/null
+++ b/plugins/gemi.py
@@ -0,0 +1,413 @@
+# Nimbus ~ UserBot
+# Copyright (C) 2023 NimbusTheCloud
+#
+# This file is a part of < https://github.com/ufoptg/Nimbus/ >
+# PLease read the GNU Affero General Public License in
+# .
+# by @SoulOfSukuna
+"""
+Gemini Command Handler
+
+This script provides the `.gemini` command to interact with Google's Gemini AI for generating content, selecting models, and managing chat history.
+
+Available Gemini Models:
+- `gemini-2.0-flash-exp` ➔ Trait: `g2f-exp` (Default model)
+- `gemini-1.5-flash` ➔ Trait: `g1f`
+- `gemini-1.5-flash-8b` ➔ Trait: `g1f8b`
+- `gemini-1.5-pro` ➔ Trait: `g1p`
+
+Features:
+1. Query Gemini AI:
+ - `.gemini ` ➔ Generates a response using the currently selected model.
+ - Example: `.gemini Write a poem about the stars.`
+
+2. Select a Model:
+ - `.gemini -m ` ➔ Selects a specific model based on its trait.
+ - Example: `.gemini -m g1f` ➔ Switches to the `gemini-1.5-flash` model.
+ - If an invalid trait is provided, an error message will be returned.
+
+3. Clear Chat History:
+ - `.gemini -c` ➔ Clears the chat history stored in memory.
+ - Example: `.gemini -c` ➔ Removes all previous queries and responses.
+
+4. Handle Long Responses:
+ - If the response exceeds Telegram's character limit (4096 characters), it will be sent as a `.txt` file.
+
+5. Reply-Based Query:
+ - Reply to a message with `.gemini write a cool caption for this image` ➔ Uses the replied message's content as the query and processes the image.
+
+Examples:
+- `.gemini Tell me a joke about programmers.`
+- `.gemini -m g2f-exp`
+- `.gemini -c`
+- Reply to an image with `.gemini write a cool caption for this image`
+"""
+
+import asyncio
+import mimetypes
+from collections import deque, defaultdict
+from io import BytesIO
+from os import system, path, remove
+from googleapiclient.discovery import build
+import time
+import logging
+from bs4 import BeautifulSoup
+
+try:
+ import google.generativeai as genai
+except ImportError:
+ system("pip install -q google-generativeai")
+ import google.generativeai as genai
+
+try:
+ from PIL import Image
+except ImportError:
+ system("pip install -q Pillow")
+ from PIL import Image
+
+from typing import Optional
+
+from . import (
+ ultroid_cmd,
+ async_searcher,
+ check_filename,
+ udB,
+ LOGS,
+ download_file,
+ run_async,
+)
+
+MODELS = [
+ {"id": "gemini-2.0-flash-exp", "traits": ["g2f-exp"]},
+ {"id": "gemini-1.5-flash", "traits": ["g1f"]},
+ {"id": "gemini-1.5-flash-8b", "traits": ["g1f8b"]},
+ {"id": "gemini-1.5-pro", "traits": ["g1p"]},
+]
+
+
+def select_model(trait: str) -> Optional[str]:
+ """Selects the Gemini model ID based on the provided trait."""
+ for model in MODELS:
+ if trait in model["traits"]:
+ return model["id"]
+ return None
+
+logging.getLogger("googleapiclient.discovery_cache").setLevel(logging.WARNING)
+
+CONFIG = {"model": select_model("g2f-exp")}
+
+GEMINI_CHAT_HISTORY = defaultdict(lambda: deque(maxlen=80))
+
+async def generate_content_with_search(prompt, model):
+ try:
+ search_results = await google_search(prompt)
+
+ search_summary = "\n".join(
+ [f"{idx + 1}. {res['title']} - {res['snippet']}" for idx, res in enumerate(search_results)]
+ )
+
+
+ enhanced_prompt = (
+ f"Use the following search results to create a comprehensive response:\n\n"
+ f"{search_summary}\n\n"
+ f"Original Query: {prompt}"
+ )
+
+ response = await model.generate_content_async(enhanced_prompt)
+ return response.text.strip()
+
+ except Exception as e:
+ return f"An error occurred while including search results: {e}. Generating content...\n\n{model.generate_content(prompt).text.strip()}"
+
+async def fetch_full_content(url):
+ try:
+ api_url = f"https://scraper.api.airforce/scrape?url={url}"
+ response = await async_searcher(api_url)
+
+ soup = BeautifulSoup(response, "html.parser")
+ main_content = soup.select_one("article") or soup.select_one("main") or soup
+ paragraphs = [
+ para.get_text(separator=" ").strip()
+ for para in main_content.find_all("p")
+ if len(para.get_text(strip=True)) > 30
+ and not any(
+ keyword in para.get_text().lower()
+ for keyword in [
+ "privacy",
+ "cookie",
+ "subscribe",
+ "sign up",
+ "terms",
+ "all rights reserved",
+ "see all",
+ "see more",
+ ]
+ )
+ ]
+ full_text = (
+ " ".join(paragraphs[:5]) if paragraphs else "No main content available."
+ )
+ return full_text
+
+ except Exception as e:
+ return f"Error fetching content: {e}"
+
+async def google_search(query):
+ api_key = "AIzaSyAOhKEVXRX-DJbxjyUz5Ol54qCygeRQRTA"
+ cse_id = "a44275f02ca2946da"
+ service = build("customsearch", "v1", developerKey=api_key)
+
+ results = service.cse().list(q=query, cx=cse_id, gl="AU").execute()
+ search_items = results.get("items", [])
+
+ search_results = await asyncio.gather(
+ *(fetch_search_result(item) for item in search_items)
+ )
+
+ return search_results
+
+async def fetch_search_result(item):
+ title = item.get("title")
+ link = item.get("link")
+ snippet = item.get("snippet")
+ full_content = await fetch_full_content(link)
+ return {
+ "title": title,
+ "link": link,
+ "snippet": snippet,
+ "full_content": full_content or "No additional content available."
+ }
+
+async def process_file(file_path: str) -> str:
+ """
+ Uploads a file to Gemini and returns the file URL.
+ """
+ try:
+ mime_type, _ = mimetypes.guess_type(file_path)
+ if not mime_type:
+ mime_type = 'application/octet-stream'
+ file_url = await asyncio.to_thread(genai.upload_file, file_path, mime_type=mime_type)
+ return file_url
+ except Exception as exc:
+ LOGS.error(f"File upload failed: {exc}")
+ raise
+
+async def process_video_file(file_path: str) -> str:
+ """
+ Uploads a video to Gemini and returns the file URL.
+ """
+ try:
+ video_file = await asyncio.to_thread(genai.upload_file, path=file_path)
+ while video_file.state.name == "PROCESSING":
+ await asyncio.sleep(10)
+ video_file = genai.get_file(video_file.name)
+
+ if video_file.state.name == "FAILED":
+ raise ValueError(video_file.state.name)
+ return video_file
+ except Exception as exc:
+ LOGS.error(f"File upload failed: {exc}")
+ raise
+
+async def process_image_with_pillow(file_path: str) -> Optional[str]:
+ """
+ Processes an image file using PIL.Image, saves it temporarily,
+ uploads it to Gemini, and returns the file URL.
+ """
+ try:
+ with Image.open(file_path) as img:
+ img = img.convert("RGB")
+ buffer = BytesIO()
+ buffer.name = "processed_image.jpeg"
+ img.save(buffer, format="JPEG", quality=90)
+ buffer.seek(0)
+
+ temp_image_path = "temp_processed_image.jpeg"
+ with open(temp_image_path, "wb") as temp_file:
+ temp_file.write(buffer.read())
+
+ file_url = await process_file(temp_image_path)
+
+ remove(temp_image_path)
+
+ return file_url
+ except Exception as exc:
+ LOGS.error(f"Image processing failed: {exc}")
+ return None
+
+
+async def handle_multimodal_input(event, e) -> Optional[str]:
+ """
+ Checks and processes images, audio, or video in a replied message.
+ Ensures cleanup of downloaded files.
+ Returns the file URL or None if processing fails.
+ """
+ temp_file = None
+ try:
+ if event.photo:
+ temp_file = await event.download_media()
+ await e.eor("Processing image with Pillow...")
+ return await process_image_with_pillow(temp_file)
+ elif event.voice or event.audio:
+ temp_file = await event.download_media()
+ await e.eor("Uploading audio...")
+ return await process_file(temp_file)
+ elif event.video:
+ temp_file = await event.download_media()
+ await e.eor("Uploading video...")
+ return await process_video_file(temp_file)
+ except Exception as exc:
+ LOGS.error(f"Error processing media: {exc}")
+ finally:
+ if temp_file and path.exists(temp_file):
+ try:
+ remove(temp_file)
+ LOGS.info(f"Cleaned up temporary file: {temp_file}")
+ except Exception as cleanup_exc:
+ LOGS.warning(f"Failed to clean up temporary file: {cleanup_exc}")
+ return None
+
+
+async def get_gemini_response(user_id: int, query: str, api_key: str, file_url: Optional[str] = None) -> str:
+ """
+ Generates a response from the selected Gemini model based on the user query.
+ Includes the user's chat history in the request.
+ If a file URL is provided, it is included in the content generation.
+ """
+ try:
+ genai.configure(api_key=api_key)
+ model = genai.GenerativeModel(CONFIG["model"])
+
+ chat_history = GEMINI_CHAT_HISTORY[user_id]
+
+ if chat_history:
+ formatted_history = "\n".join(
+ [f"{msg['role']}: {msg['content']}" for msg in chat_history]
+ )
+ if file_url:
+ content = [file_url, "\n\n", f"{formatted_history}\nuser: {query}"]
+ else:
+ content = f"{formatted_history}\nuser: {query}"
+ else:
+ if file_url:
+ content = [file_url, "\n\n", query]
+ else:
+ content = query
+
+ # Key Addition: Handle queries without file_url using Google Search
+ if not file_url:
+ response = await generate_content_with_search(query, model)
+ return response
+
+ response = await asyncio.to_thread(model.generate_content, content)
+ return response.text.strip()
+ except Exception as exc:
+ LOGS.error(f"Error generating response: {exc}")
+ raise
+
+
+@ultroid_cmd(pattern=r"gemi(?:\s+([\s\S]*))?$")
+async def gemini_handler(e):
+ """
+ Handles the .gemini command with optional model selection.
+ """
+ args = e.pattern_match.group(1)
+
+ trait = None
+ user_query = None
+ file_url = None
+
+ try:
+ user_id = e.sender.id
+ except AttributeError:
+ user_id = e.from_id.user_id
+
+ if args:
+ if args.startswith("-m"):
+ trait = args[3:].lower().strip()
+ selected_model = select_model(trait)
+ if not selected_model:
+ return await e.eor("❌ **Error:** Invalid model trait specified.", time=10)
+ CONFIG["model"] = selected_model
+ return await e.eor(f"✅ **Success:** Selected Model: `{CONFIG['model']}`", time=10)
+ elif args.strip().lower() == "-c":
+ GEMINI_CHAT_HISTORY[user_id].clear()
+ return await e.eor("🧹 **Success:** Cleared your Gemini Chat History!", time=6)
+ else:
+ user_query = args.strip()
+
+ api_key = udB.get_key("GEMINI_API")
+ if not api_key:
+ return await e.eor(
+ "⚠️ **Error:** `GEMINI_API` key missing. Please set it using `.setvar GEMINI_API your_api_key_here`.",
+ time=10,
+ )
+
+ query = user_query
+ file_url = None
+
+ reply = await e.get_reply_message()
+ if reply:
+ # New logic to handle file content
+ if (
+ reply.file
+ and reply.file.mime_type in ["text/x-python", "text/plain"]
+ ):
+ # Download the file and read its content
+ file = await reply.download_media(BytesIO())
+ file.seek(0)
+ query = file.read().decode("utf-8")
+
+ multimodal_content = await handle_multimodal_input(reply, e)
+ if multimodal_content:
+ file_url = multimodal_content
+ if not query:
+ if reply.photo:
+ query = "Analyse this image"
+ elif reply.voice or reply.audio:
+ query = "Analyse this audio."
+ elif reply.video:
+ query = "Analyse this video"
+ elif reply.text and not query:
+ query = reply.text.strip()
+
+ if not query and not file_url:
+ return await e.eor(
+ "💬 **Usage:** `.gemini `\n*Provide a query or reply with media to generate content using Gemini AI.*",
+ time=5,
+ )
+
+ processing_message = await e.eor(f"🔄 **Processing your request using `{CONFIG['model']}`...**")
+
+ GEMINI_CHAT_HISTORY[user_id].append({"role": "user", "content": query})
+
+ try:
+ response = await get_gemini_response(user_id, query, api_key, file_url=file_url)
+ GEMINI_CHAT_HISTORY[user_id].append({"role": "assistant", "content": response})
+ except Exception as exc:
+ LOGS.warning(f"Gemini response generation failed: {exc}", exc_info=True)
+ if query:
+ GEMINI_CHAT_HISTORY[user_id].pop()
+ return await processing_message.edit(f"❌ **Error:** {exc}")
+
+ if len(response) < 4096:
+ reply_text = f"📄 **Gemini Response:**\n\n{response}"
+ await processing_message.edit(reply_text, parse_mode="markdown")
+ else:
+ buffer = BytesIO()
+ try:
+ buffer.write(response.encode('utf-8'))
+ buffer.seek(0)
+ buffer.name = "gemini_response.txt"
+ await e.client.send_file(
+ e.chat_id,
+ buffer,
+ caption="📄 **Gemini Response:**",
+ reply_to=e.reply_to_msg_id,
+ )
+ except Exception as exc:
+ LOGS.error(f"Error sending file: {exc}")
+ await processing_message.edit("❌ **Error:** Failed to send the response as a file.")
+ finally:
+ buffer.close()
+ await processing_message.delete()
diff --git a/plugins/giftools.py b/plugins/giftools.py
new file mode 100644
index 0000000000000000000000000000000000000000..38fdb1f79e4869ac71b7e170d692abf13697f3d1
--- /dev/null
+++ b/plugins/giftools.py
@@ -0,0 +1,128 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+"""
+✘ Commands Available
+
+•`{i}invertgif`
+ Make Gif Inverted(negative).
+
+•`{i}bwgif`
+ Make Gif black and white
+
+•`{i}rvgif`
+ Reverse a gif
+
+•`{i}vtog`
+ Reply To Video , It will Create Gif
+ Video to Gif
+
+•`{i}gif `
+ Send video regarding to query.
+"""
+import os
+import random
+import time
+from datetime import datetime as dt
+
+from . import HNDLR, LOGS, bash, downloader, get_string, mediainfo, ultroid_cmd
+
+
+@ultroid_cmd(pattern="(bw|invert)gif$")
+async def igif(e):
+ match = e.pattern_match.group(1).strip()
+ a = await e.get_reply_message()
+ if not (a and a.media):
+ return await e.eor("`Reply To gif only`", time=5)
+ wut = mediainfo(a.media)
+ if "gif" not in wut:
+ return await e.eor("`Reply To Gif Only`", time=5)
+ xx = await e.eor(get_string("com_1"))
+ z = await a.download_media()
+ if match == "bw":
+ cmd = f'ffmpeg -i "{z}" -vf format=gray ult.gif -y'
+ else:
+ cmd = f'ffmpeg -i "{z}" -vf lutyuv="y=negval:u=negval:v=negval" ult.gif -y'
+ try:
+ await bash(cmd)
+ await e.client.send_file(e.chat_id, "ult.gif", supports_streaming=True)
+ os.remove(z)
+ os.remove("ult.gif")
+ await xx.delete()
+ except Exception as er:
+ LOGS.info(er)
+
+
+@ultroid_cmd(pattern="rvgif$")
+async def reverse_gif(event):
+ a = await event.get_reply_message()
+ if not (a and a.media) and "video" not in mediainfo(a.media):
+ return await event.eor("`Reply To Video only`", time=5)
+ msg = await event.eor(get_string("com_1"))
+ file = await a.download_media()
+ await bash(f'ffmpeg -i "{file}" -vf reverse -af areverse reversed.mp4 -y')
+ await event.respond("- **Reversed Video/GIF**", file="reversed.mp4")
+ await msg.delete()
+ os.remove(file)
+ os.remove("reversed.mp4")
+
+
+@ultroid_cmd(pattern="gif( (.*)|$)")
+async def gifs(ult):
+ get = ult.pattern_match.group(1).strip()
+ xx = random.randint(0, 5)
+ n = 0
+ if ";" in get:
+ try:
+ n = int(get.split(";")[-1])
+ except IndexError:
+ pass
+ if not get:
+ return await ult.eor(f"`{HNDLR}gif `")
+ m = await ult.eor(get_string("com_2"))
+ gifs = await ult.client.inline_query("gif", get)
+ if not n:
+ await gifs[xx].click(
+ ult.chat_id, reply_to=ult.reply_to_msg_id, silent=True, hide_via=True
+ )
+ else:
+ for x in range(n):
+ await gifs[x].click(
+ ult.chat_id, reply_to=ult.reply_to_msg_id, silent=True, hide_via=True
+ )
+ await m.delete()
+
+
+@ultroid_cmd(pattern="vtog$")
+async def vtogif(e):
+ a = await e.get_reply_message()
+ if not (a and a.media):
+ return await e.eor("`Reply To video only`", time=5)
+ wut = mediainfo(a.media)
+ if "video" not in wut:
+ return await e.eor("`Reply To Video Only`", time=5)
+ xx = await e.eor(get_string("com_1"))
+ dur = a.media.document.attributes[0].duration
+ tt = time.time()
+ if int(dur) < 120:
+ z = await a.download_media()
+ await bash(
+ f'ffmpeg -i {z} -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 ult.gif -y'
+ )
+ else:
+ filename = a.file.name
+ if not filename:
+ filename = "video_" + dt.now().isoformat("_", "seconds") + ".mp4"
+ vid = await downloader(filename, a.media.document, xx, tt, get_string("com_5"))
+ z = vid.name
+ await bash(
+ f'ffmpeg -ss 3 -t 100 -i {z} -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 ult.gif'
+ )
+
+ await e.client.send_file(e.chat_id, "ult.gif", support_stream=True)
+ os.remove(z)
+ os.remove("ult.gif")
+ await xx.delete()
diff --git a/plugins/glitch.py b/plugins/glitch.py
new file mode 100644
index 0000000000000000000000000000000000000000..a612e959e57fe8a9c75c9af5965d03b3d8368612
--- /dev/null
+++ b/plugins/glitch.py
@@ -0,0 +1,42 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+"""
+✘ Commands Available -
+
+•`{i}glitch `
+ gives a glitchy gif.
+"""
+import os
+
+from . import bash, get_string, mediainfo, ultroid_cmd
+
+
+@ultroid_cmd(pattern="glitch$")
+async def _(e):
+ try:
+ import glitch_me # ignore :pylint
+ except ModuleNotFoundError:
+ await bash(
+ "pip install -e git+https://github.com/1Danish-00/glitch_me.git#egg=glitch_me"
+ )
+ reply = await e.get_reply_message()
+ if not reply or not reply.media:
+ return await e.eor(get_string("cvt_3"))
+ xx = await e.eor(get_string("glitch_1"))
+ wut = mediainfo(reply.media)
+ if wut.startswith(("pic", "sticker")):
+ ok = await reply.download_media()
+ elif reply.document and reply.document.thumbs:
+ ok = await reply.download_media(thumb=-1)
+ else:
+ return await xx.eor(get_string("com_4"))
+ cmd = f"glitch_me gif --line_count 200 -f 10 -d 50 '{ok}' ult.gif"
+ await bash(cmd)
+ await e.reply(file="ult.gif", force_document=False)
+ await xx.delete()
+ os.remove(ok)
+ os.remove("ult.gif")
diff --git a/plugins/globaltools.py b/plugins/globaltools.py
new file mode 100644
index 0000000000000000000000000000000000000000..087db364c488745a470477c022f0b978c7cbc6a7
--- /dev/null
+++ b/plugins/globaltools.py
@@ -0,0 +1,753 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+"""
+✘ Commands Available -
+
+• `{i}gban `
+• `{i}ungban`
+ Ban/Unban Globally.
+
+• `{i}gstat `
+ Check if user is GBanned.
+
+• `{i}listgban` : List all GBanned users.
+
+• `{i}gmute` | `{i}ungmute`
+ Mute/UnMute Globally.
+
+• `{i}gkick ` `Globally Kick User`
+• `{i}gcast ` `Globally Send msg in all grps`
+
+• `{i}gadmincast ` `Globally broadcast in your admin chats`
+• `{i}gucast ` `Globally send msg in all pm users`
+
+• `{i}gblacklist `
+ globally promote user where you are admin
+ - Set whether To promote only in groups/channels/all.
+ Eg- `gpromote group boss` ~ promotes user in all grps.
+ `gpromote @username all sar` ~ promote the user in all group & channel
+• `{i}gdemote` - `demote user globally`
+"""
+import asyncio
+import os
+
+from telethon.errors.rpcerrorlist import ChatAdminRequiredError, FloodWaitError
+from telethon.tl.functions.channels import EditAdminRequest
+from telethon.tl.functions.contacts import BlockRequest, UnblockRequest
+from telethon.tl.types import ChatAdminRights, User
+
+from pyUltroid.dB import DEVLIST
+from pyUltroid.dB.base import KeyManager
+from pyUltroid.dB.gban_mute_db import (
+ gban,
+ gmute,
+ is_gbanned,
+ is_gmuted,
+ list_gbanned,
+ ungban,
+ ungmute,
+)
+from pyUltroid.fns.tools import create_tl_btn, format_btn, get_msg_button
+
+from . import (
+ HNDLR,
+ LOGS,
+ NOSPAM_CHAT,
+ OWNER_NAME,
+ eod,
+ eor,
+ get_string,
+ inline_mention,
+ ultroid_bot,
+ ultroid_cmd,
+)
+from ._inline import something
+
+_gpromote_rights = ChatAdminRights(
+ add_admins=False,
+ invite_users=True,
+ change_info=False,
+ ban_users=True,
+ delete_messages=True,
+ pin_messages=True,
+)
+
+_gdemote_rights = ChatAdminRights(
+ add_admins=False,
+ invite_users=False,
+ change_info=False,
+ ban_users=False,
+ delete_messages=False,
+ pin_messages=False,
+)
+
+keym = KeyManager("GBLACKLISTS", cast=list)
+
+
+@ultroid_cmd(pattern="gpromote( (.*)|$)", fullsudo=True)
+async def _(e):
+ x = e.pattern_match.group(1).strip()
+ ultroid_bot = e.client
+ if not x:
+ return await e.eor(get_string("schdl_2"), time=5)
+ user = await e.get_reply_message()
+ if user:
+ ev = await e.eor("`Promoting Replied User Globally`")
+ ok = e.text.split()
+ key = "all"
+ if len(ok) > 1 and (("group" in ok[1]) or ("channel" in ok[1])):
+ key = ok[1]
+ rank = ok[2] if len(ok) > 2 else "AdMin"
+ c = 0
+ user.id = user.peer_id.user_id if e.is_private else user.from_id.user_id
+ async for x in e.client.iter_dialogs():
+ if (
+ "group" in key.lower()
+ and x.is_group
+ or "group" not in key.lower()
+ and "channel" in key.lower()
+ and x.is_channel
+ ):
+ try:
+ await e.client(
+ EditAdminRequest(
+ x.id,
+ user.id,
+ _gpromote_rights,
+ rank,
+ ),
+ )
+ c += 1
+ except BaseException:
+ pass
+ elif (
+ ("group" not in key.lower() or x.is_group)
+ and (
+ "group" in key.lower()
+ or "channel" not in key.lower()
+ or x.is_channel
+ )
+ and (
+ "group" in key.lower()
+ or "channel" in key.lower()
+ or x.is_group
+ or x.is_channel
+ )
+ ):
+ try:
+ await e.client(
+ EditAdminRequest(
+ x.id,
+ user.id,
+ _gpromote_rights,
+ rank,
+ ),
+ )
+ c += 1
+ except Exception as er:
+ LOGS.info(er)
+ await eor(ev, f"Promoted The Replied Users in Total : {c} {key} chats")
+ else:
+ k = e.text.split()
+ if not k[1]:
+ return await eor(
+ e, "`Give someone's username/id or replied to user.", time=5
+ )
+ user = k[1]
+ if user.isdigit():
+ user = int(user)
+ try:
+ name = await e.client.get_entity(user)
+ except BaseException:
+ return await e.eor(f"`No User Found Regarding {user}`", time=5)
+ ev = await e.eor(f"`Promoting {name.first_name} globally.`")
+ key = "all"
+ if len(k) > 2 and (("group" in k[2]) or ("channel" in k[2])):
+ key = k[2]
+ rank = k[3] if len(k) > 3 else "AdMin"
+ c = 0
+ async for x in e.client.iter_dialogs():
+ if (
+ "group" in key.lower()
+ and x.is_group
+ or "group" not in key.lower()
+ and "channel" in key.lower()
+ and x.is_channel
+ or "group" not in key.lower()
+ and "channel" not in key.lower()
+ and (x.is_group or x.is_channel)
+ ):
+ try:
+ await ultroid_bot(
+ EditAdminRequest(
+ x.id,
+ user,
+ _gpromote_rights,
+ rank,
+ ),
+ )
+ c += 1
+ except BaseException:
+ pass
+ await eor(ev, f"Promoted {name.first_name} in Total : {c} {key} chats.")
+
+
+@ultroid_cmd(pattern="gdemote( (.*)|$)", fullsudo=True)
+async def _(e):
+ x = e.pattern_match.group(1).strip()
+ ultroid_bot = e.client
+ if not x:
+ return await e.eor(get_string("schdl_2"), time=5)
+ user = await e.get_reply_message()
+ if user:
+ user.id = user.peer_id.user_id if e.is_private else user.from_id.user_id
+ ev = await e.eor("`Demoting Replied User Globally`")
+ ok = e.text.split()
+ key = "all"
+ if len(ok) > 1 and (("group" in ok[1]) or ("channel" in ok[1])):
+ key = ok[1]
+ rank = "Not AdMin"
+ c = 0
+ async for x in e.client.iter_dialogs():
+ if (
+ "group" in key.lower()
+ and x.is_group
+ or "group" not in key.lower()
+ and "channel" in key.lower()
+ and x.is_channel
+ or "group" not in key.lower()
+ and "channel" not in key.lower()
+ and (x.is_group or x.is_channel)
+ ):
+ try:
+ await ultroid_bot(
+ EditAdminRequest(
+ x.id,
+ user.id,
+ _gdemote_rights,
+ rank,
+ ),
+ )
+ c += 1
+ except BaseException:
+ pass
+ await eor(ev, f"Demoted The Replied Users in Total : {c} {key} chats")
+ else:
+ k = e.text.split()
+ if not k[1]:
+ return await eor(
+ e, "`Give someone's username/id or replied to user.", time=5
+ )
+ user = k[1]
+ if user.isdigit():
+ user = int(user)
+ try:
+ name = await ultroid_bot.get_entity(user)
+ except BaseException:
+ return await e.eor(f"`No User Found Regarding {user}`", time=5)
+ ev = await e.eor(f"`Demoting {name.first_name} globally.`")
+ key = "all"
+ if len(k) > 2 and (("group" in k[2]) or ("channel" in k[2])):
+ key = k[2]
+ rank = "Not AdMin"
+ c = 0
+ async for x in ultroid_bot.iter_dialogs():
+ if (
+ "group" in key.lower()
+ and x.is_group
+ or "group" not in key.lower()
+ and "channel" in key.lower()
+ and x.is_channel
+ or "group" not in key.lower()
+ and "channel" not in key.lower()
+ and (x.is_group or x.is_channel)
+ ):
+ try:
+ await ultroid_bot(
+ EditAdminRequest(
+ x.id,
+ user,
+ _gdemote_rights,
+ rank,
+ ),
+ )
+ c += 1
+ except BaseException:
+ pass
+ await eor(ev, f"Demoted {name.first_name} in Total : {c} {key} chats.")
+
+
+@ultroid_cmd(pattern="ungban( (.*)|$)", fullsudo=True)
+async def _(e):
+ xx = await e.eor("`UnGbanning...`")
+ match = e.pattern_match.group(1).strip()
+ peer = None
+ if e.reply_to_msg_id:
+ userid = (await e.get_reply_message()).sender_id
+ elif match:
+ try:
+ userid = int(match)
+ except ValueError:
+ userid = match
+ try:
+ userid = (await e.client.get_entity(userid)).id
+ except Exception as er:
+ return await xx.edit(f"Failed to get User...\nError: {er}")
+ elif e.is_private:
+ userid = e.chat_id
+ else:
+ return await xx.eor("`Reply to some msg or add their id.`", time=5)
+ if not is_gbanned(userid):
+ return await xx.edit("`User/Channel is not Gbanned...`")
+ try:
+ if not peer:
+ peer = await e.client.get_entity(userid)
+ name = inline_mention(peer)
+ except BaseException:
+ userid = int(userid)
+ name = str(userid)
+ chats = 0
+ if e.client._dialogs:
+ dialog = e.client._dialogs
+ else:
+ dialog = await e.client.get_dialogs()
+ e.client._dialogs.extend(dialog)
+ for ggban in dialog:
+ if ggban.is_group or ggban.is_channel:
+ try:
+ await e.client.edit_permissions(ggban.id, userid, view_messages=True)
+ chats += 1
+ except FloodWaitError as fw:
+ LOGS.info(
+ f"[FLOOD_WAIT_ERROR] : on Ungban\nSleeping for {fw.seconds+10}"
+ )
+ await asyncio.sleep(fw.seconds + 10)
+ try:
+ await e.client.edit_permissions(
+ ggban.id, userid, view_messages=True
+ )
+ chats += 1
+ except BaseException as er:
+ LOGS.exception(er)
+ except (ChatAdminRequiredError, ValueError):
+ pass
+ except BaseException as er:
+ LOGS.exception(er)
+ ungban(userid)
+ if isinstance(peer, User):
+ await e.client(UnblockRequest(userid))
+ await xx.edit(
+ f"`Ungbaned` {name} in {chats} `chats.\nRemoved from gbanwatch.`",
+ )
+
+
+@ultroid_cmd(pattern="gban( (.*)|$)", fullsudo=True)
+async def _(e):
+ xx = await e.eor("`Gbanning...`")
+ reason = ""
+ if e.reply_to_msg_id:
+ userid = (await e.get_reply_message()).sender_id
+ try:
+ reason = e.text.split(" ", maxsplit=1)[1]
+ except IndexError:
+ pass
+ elif e.pattern_match.group(1).strip():
+ usr = e.text.split(maxsplit=2)[1]
+ try:
+ userid = await e.client.parse_id(usr)
+ except ValueError:
+ userid = usr
+ try:
+ reason = e.text.split(maxsplit=2)[2]
+ except IndexError:
+ pass
+ elif e.is_private:
+ userid = e.chat_id
+ try:
+ reason = e.text.split(" ", maxsplit=1)[1]
+ except IndexError:
+ pass
+ else:
+ return await xx.eor("`Reply to some msg or add their id.`", time=5)
+ user = None
+ try:
+ user = await e.client.get_entity(userid)
+ name = inline_mention(user)
+ except BaseException:
+ userid = int(userid)
+ name = str(userid)
+ chats = 0
+ if userid == ultroid_bot.uid:
+ return await xx.eor("`I can't gban myself.`", time=3)
+ elif userid in DEVLIST:
+ return await xx.eor("`I can't gban my Developers.`", time=3)
+ elif is_gbanned(userid):
+ return await eod(
+ xx,
+ "`User is already gbanned and added to gbanwatch.`",
+ time=4,
+ )
+ if e.client._dialogs:
+ dialog = e.client._dialogs
+ else:
+ dialog = await e.client.get_dialogs()
+ e.client._dialogs.extend(dialog)
+ for ggban in dialog:
+ if ggban.is_group or ggban.is_channel:
+ try:
+ await e.client.edit_permissions(ggban.id, userid, view_messages=False)
+ chats += 1
+ except FloodWaitError as fw:
+ LOGS.info(
+ f"[FLOOD_WAIT_ERROR] : on GBAN Command\nSleeping for {fw.seconds+10}"
+ )
+ await asyncio.sleep(fw.seconds + 10)
+ try:
+ await e.client.edit_permissions(
+ ggban.id, userid, view_messages=False
+ )
+ chats += 1
+ except BaseException as er:
+ LOGS.exception(er)
+ except (ChatAdminRequiredError, ValueError):
+ pass
+ except BaseException as er:
+ LOGS.exception(er)
+ gban(userid, reason)
+ if isinstance(user, User):
+ await e.client(BlockRequest(userid))
+ gb_msg = f"**#Gbanned** {name} `in {chats} chats and added to gbanwatch!`"
+ if reason:
+ gb_msg += f"\n**Reason** : {reason}"
+ await xx.edit(gb_msg)
+
+
+@ultroid_cmd(pattern="g(admin|)cast( (.*)|$)", fullsudo=True)
+async def gcast(event):
+ text, btn, reply = "", None, None
+ if xx := event.pattern_match.group(2):
+ msg, btn = get_msg_button(event.text.split(maxsplit=1)[1])
+ elif event.is_reply:
+ reply = await event.get_reply_message()
+ msg = reply.text
+ if reply.buttons:
+ btn = format_btn(reply.buttons)
+ else:
+ msg, btn = get_msg_button(msg)
+ else:
+ return await eor(
+ event, "`Give some text to Globally Broadcast or reply a message..`"
+ )
+
+ kk = await event.eor("`Globally Broadcasting Msg...`")
+ er = 0
+ done = 0
+ err = ""
+ if event.client._dialogs:
+ dialog = event.client._dialogs
+ else:
+ dialog = await event.client.get_dialogs()
+ event.client._dialogs.extend(dialog)
+ for x in dialog:
+ if x.is_group:
+ chat = x.entity.id
+ if (
+ not keym.contains(chat)
+ and int(f"-100{str(chat)}") not in NOSPAM_CHAT
+ and (
+ (
+ event.text[2:7] != "admin"
+ or (x.entity.admin_rights or x.entity.creator)
+ )
+ )
+ ):
+ try:
+ if btn:
+ bt = create_tl_btn(btn)
+ await something(
+ event,
+ msg,
+ reply.media if reply else None,
+ bt,
+ chat=chat,
+ reply=False,
+ )
+ else:
+ await event.client.send_message(
+ chat, msg, file=reply.media if reply else None
+ )
+ done += 1
+ except FloodWaitError as fw:
+ await asyncio.sleep(fw.seconds + 10)
+ try:
+ if btn:
+ bt = create_tl_btn(btn)
+ await something(
+ event,
+ msg,
+ reply.media if reply else None,
+ bt,
+ chat=chat,
+ reply=False,
+ )
+ else:
+ await event.client.send_message(
+ chat, msg, file=reply.media if reply else None
+ )
+ done += 1
+ except Exception as rr:
+ err += f"• {rr}\n"
+ er += 1
+ except BaseException as h:
+ err += f"• {str(h)}" + "\n"
+ er += 1
+ text += f"Done in {done} chats, error in {er} chat(s)"
+ if err != "":
+ open("gcast-error.log", "w+").write(err)
+ text += f"\nYou can do `{HNDLR}ul gcast-error.log` to know error report."
+ await kk.edit(text)
+
+
+@ultroid_cmd(pattern="gucast( (.*)|$)", fullsudo=True)
+async def gucast(event):
+ msg, btn, reply = "", None, None
+ if xx := event.pattern_match.group(1).strip():
+ msg, btn = get_msg_button(event.text.split(maxsplit=1)[1])
+ elif event.is_reply:
+ reply = await event.get_reply_message()
+ msg = reply.text
+ if reply.buttons:
+ btn = format_btn(reply.buttons)
+ else:
+ msg, btn = get_msg_button(msg)
+ else:
+ return await eor(
+ event, "`Give some text to Globally Broadcast or reply a message..`"
+ )
+ kk = await event.eor("`Globally Broadcasting Msg...`")
+ er = 0
+ done = 0
+ if event.client._dialogs:
+ dialog = event.client._dialogs
+ else:
+ dialog = await event.client.get_dialogs()
+ event.client._dialogs.extend(dialog)
+ for x in dialog:
+ if x.is_user and not x.entity.bot:
+ chat = x.id
+ if not keym.contains(chat):
+ try:
+ if btn:
+ bt = create_tl_btn(btn)
+ await something(
+ event,
+ msg,
+ reply.media if reply else None,
+ bt,
+ chat=chat,
+ reply=False,
+ )
+ else:
+ await event.client.send_message(
+ chat, msg, file=reply.media if reply else None
+ )
+ done += 1
+ except BaseException:
+ er += 1
+ await kk.edit(f"Done in {done} chats, error in {er} chat(s)")
+
+
+@ultroid_cmd(pattern="gkick( (.*)|$)", fullsudo=True)
+async def gkick(e):
+ xx = await e.eor("`Gkicking...`")
+ if e.reply_to_msg_id:
+ userid = (await e.get_reply_message()).sender_id
+ elif e.pattern_match.group(1).strip():
+ userid = await e.client.parse_id(e.pattern_match.group(1).strip())
+ elif e.is_private:
+ userid = e.chat_id
+ else:
+ return await xx.edit("`Reply to some msg or add their id.`", time=5)
+ name = (await e.client.get_entity(userid)).first_name
+ chats = 0
+ if userid == ultroid_bot.uid:
+ return await xx.eor("`I can't gkick myself.`", time=3)
+ if userid in DEVLIST:
+ return await xx.eor("`I can't gkick my Developers.`", time=3)
+ if e.client._dialogs:
+ dialog = e.client._dialogs
+ else:
+ dialog = await e.client.get_dialogs()
+ e.client._dialogs.extend(dialog)
+ for gkick in dialog:
+ if gkick.is_group or gkick.is_channel:
+ try:
+ await e.client.kick_participant(gkick.id, userid)
+ chats += 1
+ except BaseException:
+ pass
+ await xx.edit(f"`Gkicked` [{name}](tg://user?id={userid}) `in {chats} chats.`")
+
+
+@ultroid_cmd(pattern="gmute( (.*)|$)", fullsudo=True)
+async def _(e):
+ xx = await e.eor("`Gmuting...`")
+ if e.reply_to_msg_id:
+ userid = (await e.get_reply_message()).sender_id
+ elif e.pattern_match.group(1).strip():
+ userid = await e.client.parse_id(e.pattern_match.group(1).strip())
+ elif e.is_private:
+ userid = e.chat_id
+ else:
+ return await xx.eor("`Reply to some msg or add their id.`", tome=5, time=5)
+ name = await e.client.get_entity(userid)
+ chats = 0
+ if userid == ultroid_bot.uid:
+ return await xx.eor("`I can't gmute myself.`", time=3)
+ if userid in DEVLIST:
+ return await xx.eor("`I can't gmute my Developers.`", time=3)
+ if is_gmuted(userid):
+ return await xx.eor("`User is already gmuted.`", time=4)
+ if e.client._dialogs:
+ dialog = e.client._dialogs
+ else:
+ dialog = await e.client.get_dialogs()
+ e.client._dialogs.extend(dialog)
+ for onmute in dialog:
+ if onmute.is_group:
+ try:
+ await e.client.edit_permissions(onmute.id, userid, send_messages=False)
+ chats += 1
+ except BaseException:
+ pass
+ gmute(userid)
+ await xx.edit(f"`Gmuted` {inline_mention(name)} `in {chats} chats.`")
+
+
+@ultroid_cmd(pattern="ungmute( (.*)|$)", fullsudo=True)
+async def _(e):
+ xx = await e.eor("`UnGmuting...`")
+ if e.reply_to_msg_id:
+ userid = (await e.get_reply_message()).sender_id
+ elif e.pattern_match.group(1).strip():
+ userid = await e.client.parse_id(e.pattern_match.group(1).strip())
+ elif e.is_private:
+ userid = e.chat_id
+ else:
+ return await xx.eor("`Reply to some msg or add their id.`", time=5)
+ name = (await e.client.get_entity(userid)).first_name
+ chats = 0
+ if not is_gmuted(userid):
+ return await xx.eor("`User is not gmuted.`", time=3)
+ if e.client._dialogs:
+ dialog = e.client._dialogs
+ else:
+ dialog = await e.client.get_dialogs()
+ e.client._dialogs.extend(dialog)
+ for hurr in dialog:
+ if hurr.is_group:
+ try:
+ await e.client.edit_permissions(hurr.id, userid, send_messages=True)
+ chats += 1
+ except BaseException:
+ pass
+ ungmute(userid)
+ await xx.edit(f"`Ungmuted` {inline_mention(name)} `in {chats} chats.`")
+
+
+@ultroid_cmd(
+ pattern="listgban$",
+)
+async def list_gengbanned(event):
+ users = list_gbanned()
+ x = await event.eor(get_string("com_1"))
+ msg = ""
+ if not users:
+ return await x.edit("`You haven't GBanned anyone!`")
+ for i in users:
+ try:
+ name = await event.client.get_entity(int(i))
+ except BaseException:
+ name = i
+ msg += f"User: {inline_mention(name, html=True)}\n"
+ reason = users[i]
+ msg += f"Reason: {reason}\n\n" if reason is not None else "\n"
+ gbanned_users = f"List of users GBanned by {OWNER_NAME}:\n\n{msg}"
+ if len(gbanned_users) > 4096:
+ with open("gbanned.txt", "w") as f:
+ f.write(
+ gbanned_users.replace("", "")
+ .replace("", "")
+ .replace("", "")
+ )
+ await x.reply(
+ file="gbanned.txt",
+ message=f"List of users GBanned by {inline_mention(ultroid_bot.me)}",
+ )
+ os.remove("gbanned.txt")
+ await x.delete()
+ else:
+ await x.edit(gbanned_users, parse_mode="html")
+
+
+@ultroid_cmd(
+ pattern="gstat( (.*)|$)",
+)
+async def gstat_(e):
+ xx = await e.eor(get_string("com_1"))
+ if e.is_private:
+ userid = (await e.get_chat()).id
+ elif e.reply_to_msg_id:
+ userid = (await e.get_reply_message()).sender_id
+ elif e.pattern_match.group(1).strip():
+ try:
+ userid = await e.client.parse_id(e.pattern_match.group(1).strip())
+ except Exception as err:
+ return await xx.eor(f"{err}", time=10)
+ else:
+ return await xx.eor("`Reply to some msg or add their id.`", time=5)
+ name = (await e.client.get_entity(userid)).first_name
+ msg = f"**{name} is "
+ is_banned = is_gbanned(userid)
+ reason = list_gbanned().get(userid)
+ if is_banned:
+ msg += "Globally Banned"
+ msg += f" with reason** `{reason}`" if reason else ".**"
+ else:
+ msg += "not Globally Banned.**"
+ await xx.edit(msg)
+
+
+@ultroid_cmd(pattern="gblacklist$")
+async def blacklist_(event):
+ await gblacker(event, "add")
+
+
+@ultroid_cmd(pattern="ungblacklist$")
+async def ungblacker(event):
+ await gblacker(event, "remove")
+
+
+async def gblacker(event, type_):
+ try:
+ chat_id = int(event.text.split(maxsplit=1)[1])
+ try:
+ chat_id = (await event.client.get_entity(chat_id)).id
+ except Exception as e:
+ return await event.eor(f"**ERROR**\n`{str(e)}`")
+ except IndexError:
+ chat_id = event.chat_id
+ if type_ == "add":
+ keym.add(chat_id)
+ elif type_ == "remove":
+ keym.remove(chat_id)
+ await event.eor(f"Global Broadcasts: \n{type_}ed {chat_id}")
diff --git a/plugins/gpt.py b/plugins/gpt.py
new file mode 100644
index 0000000000000000000000000000000000000000..11f9f577fc77394f34169eec2cfeca3974b5611f
--- /dev/null
+++ b/plugins/gpt.py
@@ -0,0 +1,183 @@
+import os
+from collections import deque
+from io import BytesIO
+
+from . import (
+ ultroid_cmd,
+ async_searcher,
+ udB,
+ LOGS,
+ get_paste,
+)
+
+GPT_CHAT_HISTORY = deque(maxlen=30)
+
+TELEGRAM_CHAR_LIMIT = 4096 # Telegram's message character limit
+
+
+async def pastee(data):
+ err, linky = await get_paste(data)
+ if err:
+ return f">> [Raw Code Pasted Here](https://spaceb.in/{linky})\n"
+ else:
+ LOGS.error(linky)
+ return ""
+
+
+@ultroid_cmd(
+ pattern=r"gpt( ([\s\S]*))?$",
+)
+async def openai_chat_gpt(e):
+ api_key = "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"
+ if not api_key:
+ return await e.eor("`OPENAI_API` key missing..", time=10)
+
+ query = e.pattern_match.group(2)
+ reply = await e.get_reply_message()
+
+ file_content = None
+
+ if query:
+ # Check if query contains 'from filename'
+ if ' from ' in query:
+ query_text, filename = query.split(' from ', 1)
+ query_text = query_text.strip()
+ filename = filename.strip()
+ # Attempt to find and read the file from media in chat
+ file_found = False
+ async for message in e.client.iter_messages(e.chat_id, reverse=True, limit=50):
+ if message.media and message.file.name == filename:
+ if (message.file.name.endswith(".txt") or message.file.name.endswith(".py")):
+ file = await e.client.download_media(message)
+ try:
+ with open(file, "r", encoding='utf-8') as f:
+ file_content = f.read()
+ except Exception as exc:
+ LOGS.error(f"Error reading file: {exc}")
+ return await e.eor("`Failed to read file content.`", time=5)
+ finally:
+ os.remove(file)
+ file_found = True
+ break
+ if not file_found:
+ return await e.eor(f"`File {filename} not found in recent messages.`", time=5)
+ if file_content:
+ query = f"{query_text}\n\n{file_content}" if query_text else file_content
+ else:
+ return await e.eor("`Failed to read file content.`", time=5)
+ else:
+ if reply and reply.media and (reply.file.name.endswith(".txt") or reply.file.name.endswith(".py")):
+ # Use the query and the replied file content
+ file = await e.client.download_media(reply)
+ try:
+ with open(file, "r", encoding='utf-8') as f:
+ file_content = f.read()
+ except Exception as exc:
+ LOGS.error(f"Error reading file: {exc}")
+ return await e.eor("`Failed to read file content.`", time=5)
+ finally:
+ os.remove(file)
+ query = f"{query}\n\n{file_content}"
+ elif reply and reply.message:
+ # Use the query and the replied text message content
+ query = f"{query}\n\n{reply.message}"
+ # Else, use query as is
+ else:
+ if reply and reply.media and (reply.file.name.endswith(".txt") or reply.file.name.endswith(".py")):
+ # Use the replied file content
+ file = await e.client.download_media(reply)
+ try:
+ with open(file, "r", encoding='utf-8') as f:
+ file_content = f.read()
+ except Exception as exc:
+ LOGS.error(f"Error reading file: {exc}")
+ return await e.eor("`Failed to read file content.`", time=5)
+ finally:
+ os.remove(file)
+ query = file_content
+ elif reply and reply.message:
+ # Use the replied text message content
+ query = reply.message
+ else:
+ return await e.eor("`Please provide a question or reply to a message or .txt/.py file.`", time=5)
+
+ if query.strip() == "-c":
+ GPT_CHAT_HISTORY.clear()
+ return await e.eor("__Cleared o1-mini Chat History!__", time=6)
+
+ eris = await e.eor(f"__Generating answer for:__\n`{query[:20]} ...`")
+ GPT_CHAT_HISTORY.append({"role": "user", "content": query})
+
+ try:
+ data = {
+ "model": "o1-mini",
+ "messages": list(GPT_CHAT_HISTORY),
+ }
+ request = await async_searcher(
+ "https://api.openai.com/v1/chat/completions",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {api_key}",
+ },
+ json=data,
+ re_json=True,
+ post=True,
+ )
+ response = request["choices"][0]["message"]["content"]
+ GPT_CHAT_HISTORY.append({"role": "assistant", "content": response})
+ except Exception as exc:
+ LOGS.warning(exc, exc_info=True)
+ GPT_CHAT_HISTORY.pop()
+ return await eris.edit(
+ f"**Error while requesting data from OpenAI:** \n> `{exc}`"
+ )
+
+ LOGS.debug(f'Tokens Used on query: {request["usage"]["completion_tokens"]}')
+
+ # Truncate query to 50 characters for display
+ truncated_query = query[:100]
+
+ # Prepare the full message
+ full_message = f"**Query:**\n~ __{truncated_query}__\n\n**o1-mini:**\n~ {response}"
+
+ # Check if response contains code blocks
+ code_blocks = []
+ in_code_block = False
+ code_block_lines = []
+ for line in response.split('\n'):
+ if line.strip().startswith('```'):
+ if in_code_block:
+ # End of code block
+ in_code_block = False
+ code_blocks.append('\n'.join(code_block_lines))
+ code_block_lines = []
+ else:
+ # Start of code block
+ in_code_block = True
+ elif in_code_block:
+ code_block_lines.append(line)
+
+ # If the response contains code blocks, select the largest one and paste it
+ if code_blocks:
+ # Select the largest code block based on length
+ largest_code_block = max(code_blocks, key=lambda block: len(block))
+ # Upload the largest code block to spaceb.in and get the link
+ paste_link = await pastee(largest_code_block)
+ else:
+ paste_link = ""
+
+ if len(full_message) <= TELEGRAM_CHAR_LIMIT:
+ # If it fits within the limit, send as a message
+ await eris.edit(full_message + f"\n\n{paste_link}")
+ else:
+ # If it exceeds the limit, send as a file and include paste link
+ file = BytesIO(full_message.encode('utf-8'))
+ file.name = "o1-mini-output.txt"
+ await eris.respond(
+ "__The query and response were too long, so they have been sent as a file.__\n\n" + paste_link,
+ file=file,
+ reply_to=e.reply_to_msg_id or e.id,
+ link_preview=False
+ )
+ await eris.delete()
+
diff --git a/plugins/greetings.py b/plugins/greetings.py
new file mode 100644
index 0000000000000000000000000000000000000000..6254a6be539c94ee6529ae141d12cb9ab7807bf1
--- /dev/null
+++ b/plugins/greetings.py
@@ -0,0 +1,205 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+"""
+✘ Commands Available -
+
+---- Welcomes ----
+• `{i}setwelcome `
+ Set welcome message in the current chat.
+
+• `{i}clearwelcome`
+ Delete the welcome in the current chat.
+
+• `{i}getwelcome`
+ Get the welcome message in the current chat.
+
+---- GoodByes ----
+• `{i}setgoodbye `
+ Set goodbye message in the current chat.
+
+• `{i}cleargoodbye`
+ Delete the goodbye in the current chat.
+
+• `{i}getgoodbye`
+ Get the goodbye message in the current chat.
+
+• `{i}thankmembers on/off`
+ Send a thank you sticker on hitting a members count of 100*x in your groups.
+"""
+import os
+
+from telegraph import upload_file as uf
+from telethon.utils import pack_bot_file_id
+
+from pyUltroid.dB.greetings_db import (
+ add_goodbye,
+ add_thanks,
+ add_welcome,
+ delete_goodbye,
+ delete_welcome,
+ get_goodbye,
+ get_welcome,
+ must_thank,
+ remove_thanks,
+)
+from pyUltroid.fns.tools import create_tl_btn, format_btn, get_msg_button
+
+from . import HNDLR, eor, get_string, mediainfo, ultroid_cmd
+from ._inline import something
+
+Note = "\n\nNote: `{mention}`, `{group}`, `{count}`, `{name}`, `{fullname}`, `{username}`, `{userid}` can be used as formatting parameters.\n\n"
+
+
+@ultroid_cmd(pattern="setwelcome", groups_only=True)
+async def setwel(event):
+ x = await event.eor(get_string("com_1"))
+ r = await event.get_reply_message()
+ btn = format_btn(r.buttons) if (r and r.buttons) else None
+ try:
+ text = event.text.split(maxsplit=1)[1]
+ except IndexError:
+ text = r.text if r else None
+ if r and r.media:
+ wut = mediainfo(r.media)
+ if wut.startswith(("pic", "gif")):
+ dl = await r.download_media()
+ variable = uf(dl)
+ os.remove(dl)
+ m = f"https://graph.org{variable[0]}"
+ elif wut == "video":
+ if r.media.document.size > 8 * 1000 * 1000:
+ return await eor(x, get_string("com_4"), time=5)
+ dl = await r.download_media()
+ variable = uf(dl)
+ os.remove(dl)
+ m = f"https://graph.org{variable[0]}"
+ elif wut == "web":
+ m = None
+ else:
+ m = pack_bot_file_id(r.media)
+ if r.text:
+ txt = r.text
+ if not btn:
+ txt, btn = get_msg_button(r.text)
+ add_welcome(event.chat_id, txt, m, btn)
+ else:
+ add_welcome(event.chat_id, None, m, btn)
+ await eor(x, get_string("grt_1"))
+ elif text:
+ if not btn:
+ txt, btn = get_msg_button(text)
+ add_welcome(event.chat_id, txt, None, btn)
+ await eor(x, get_string("grt_1"))
+ else:
+ await eor(x, get_string("grt_3"), time=5)
+
+
+@ultroid_cmd(pattern="clearwelcome$", groups_only=True)
+async def clearwel(event):
+ if not get_welcome(event.chat_id):
+ return await event.eor(get_string("grt_4"), time=5)
+ delete_welcome(event.chat_id)
+ await event.eor(get_string("grt_5"), time=5)
+
+
+@ultroid_cmd(pattern="getwelcome$", groups_only=True)
+async def listwel(event):
+ wel = get_welcome(event.chat_id)
+ if not wel:
+ return await event.eor(get_string("grt_4"), time=5)
+ msgg, med = wel["welcome"], wel["media"]
+ if wel.get("button"):
+ btn = create_tl_btn(wel["button"])
+ return await something(event, msgg, med, btn)
+ await event.reply(f"**Welcome Note in this chat**\n\n`{msgg}`", file=med)
+ await event.delete()
+
+
+@ultroid_cmd(pattern="setgoodbye", groups_only=True)
+async def setgb(event):
+ x = await event.eor(get_string("com_1"))
+ r = await event.get_reply_message()
+ btn = format_btn(r.buttons) if (r and r.buttons) else None
+ try:
+ text = event.text.split(maxsplit=1)[1]
+ except IndexError:
+ text = r.text if r else None
+ if r and r.media:
+ wut = mediainfo(r.media)
+ if wut.startswith(("pic", "gif")):
+ dl = await r.download_media()
+ variable = uf(dl)
+ os.remove(dl)
+ m = f"https://graph.org{variable[0]}"
+ elif wut == "video":
+ if r.media.document.size > 8 * 1000 * 1000:
+ return await eor(x, get_string("com_4"), time=5)
+ dl = await r.download_media()
+ variable = uf(dl)
+ os.remove(dl)
+ m = f"https://graph.org{variable[0]}"
+ elif wut == "web":
+ m = None
+ else:
+ m = pack_bot_file_id(r.media)
+ if r.text:
+ txt = r.text
+ if not btn:
+ txt, btn = get_msg_button(r.text)
+ add_goodbye(event.chat_id, txt, m, btn)
+ else:
+ add_goodbye(event.chat_id, None, m, btn)
+ await eor(x, "`Goodbye note saved`")
+ elif text:
+ if not btn:
+ txt, btn = get_msg_button(text)
+ add_goodbye(event.chat_id, txt, None, btn)
+ await eor(x, "`Goodbye note saved`")
+ else:
+ await eor(x, get_string("grt_7"), time=5)
+
+
+@ultroid_cmd(pattern="cleargoodbye$", groups_only=True)
+async def clearwgb(event):
+ if not get_goodbye(event.chat_id):
+ return await event.eor(get_string("grt_6"), time=5)
+ delete_goodbye(event.chat_id)
+ await event.eor("`Goodbye Note Deleted`", time=5)
+
+
+@ultroid_cmd(pattern="getgoodbye$", groups_only=True)
+async def listgd(event):
+ wel = get_goodbye(event.chat_id)
+ if not wel:
+ return await event.eor(get_string("grt_6"), time=5)
+ msgg = wel["goodbye"]
+ med = wel["media"]
+ if wel.get("button"):
+ btn = create_tl_btn(wel["button"])
+ return await something(event, msgg, med, btn)
+ await event.reply(f"**Goodbye Note in this chat**\n\n`{msgg}`", file=med)
+ await event.delete()
+
+
+@ultroid_cmd(pattern="thankmembers (on|off)", groups_only=True)
+async def thank_set(event):
+ type_ = event.pattern_match.group(1).strip()
+ if not type_ or type_ == "":
+ await eor(
+ event,
+ f"**Current Chat Settings:**\n**Thanking Members:** `{must_thank(event.chat_id)}`\n\nUse `{HNDLR}thankmembers on` or `{HNDLR}thankmembers off` to toggle current settings!",
+ )
+ return
+ chat = event.chat_id
+ if type_.lower() == "on":
+ add_thanks(chat)
+ elif type_.lower() == "off":
+ remove_thanks(chat)
+ await eor(
+ event,
+ f"**Done! Thank you members has been turned** `{type_.lower()}` **for this chat**!",
+ )
diff --git a/plugins/imagetools.py b/plugins/imagetools.py
new file mode 100644
index 0000000000000000000000000000000000000000..ef633427e4df89fb6d964a4fbce7f83001561f69
--- /dev/null
+++ b/plugins/imagetools.py
@@ -0,0 +1,292 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+"""
+✘ Commands Available -
+
+• `{i}border `
+ To create border around that media..
+ Ex - `{i}border 12,22,23`
+ - `{i}border 12,22,23 ; width (in number)`
+
+• `{i}grey `
+ To make it black nd white.
+
+• `{i}color `
+ To make it Colorfull.
+
+• `{i}toon `
+ To make it toon.
+
+• `{i}danger `
+ To make it look Danger.
+
+• `{i}negative `
+ To make negative image.
+
+• `{i}blur `
+ To make it blurry.
+
+• `{i}quad `
+ create a Vortex.
+
+• `{i}mirror `
+ To create mirror pic.
+
+• `{i}flip `
+ To make it flip.
+
+• `{i}sketch `
+ To draw its sketch.
+
+• `{i}blue `
+ just cool.
+
+• `{i}csample `
+ example : `{i}csample red`
+ `{i}csample #ffffff`
+
+• `{i}pixelator `
+ Create a Pixelated Image..
+"""
+import os
+
+from . import LOGS, con
+
+try:
+ import cv2
+except ImportError:
+ LOGS.error(f"{__file__}: OpenCv not Installed.")
+
+import numpy as np
+
+try:
+ from PIL import Image
+except ImportError:
+ Image = None
+ LOGS.info(f"{__file__}: PIL not Installed.")
+from telegraph import upload_file as upf
+from telethon.errors.rpcerrorlist import (
+ ChatSendMediaForbiddenError,
+ MessageDeleteForbiddenError,
+)
+
+from . import (
+ Redis,
+ async_searcher,
+ download_file,
+ get_string,
+ requests,
+ udB,
+ ultroid_cmd,
+)
+
+
+@ultroid_cmd(pattern="color$")
+async def _(event):
+ reply = await event.get_reply_message()
+ if not (reply and reply.media):
+ return await event.eor("`Reply To a Black and White Image`")
+ xx = await event.eor("`Coloring image 🎨🖌️...`")
+ image = await reply.download_media()
+ img = cv2.VideoCapture(image)
+ ret, frame = img.read()
+ cv2.imwrite("ult.jpg", frame)
+ if udB.get_key("DEEP_API"):
+ key = Redis("DEEP_API")
+ else:
+ key = "quickstart-QUdJIGlzIGNvbWluZy4uLi4K"
+ r = requests.post(
+ "https://api.deepai.org/api/colorizer",
+ files={"image": open("ult.jpg", "rb")},
+ headers={"api-key": key},
+ )
+ os.remove("ult.jpg")
+ os.remove(image)
+ if "status" in r.json():
+ return await event.edit(
+ r.json()["status"] + "\nGet api nd set `{i}setdb DEEP_API key`"
+ )
+ r_json = r.json()["output_url"]
+ await event.client.send_file(event.chat_id, r_json, reply_to=reply)
+ await xx.delete()
+
+
+@ultroid_cmd(pattern="(grey|blur|negative|danger|mirror|quad|sketch|flip|toon)$")
+async def ult_tools(event):
+ match = event.pattern_match.group(1)
+ ureply = await event.get_reply_message()
+ if not (ureply and (ureply.media)):
+ await event.eor(get_string("cvt_3"))
+ return
+ ultt = await ureply.download_media()
+ xx = await event.eor(get_string("com_1"))
+ if ultt.endswith(".tgs"):
+ xx = await xx.edit(get_string("sts_9"))
+ file = await con.convert(ultt, convert_to="png", outname="ult")
+ ult = cv2.imread(file)
+ if match == "grey":
+ ultroid = cv2.cvtColor(ult, cv2.COLOR_BGR2GRAY)
+ elif match == "blur":
+ ultroid = cv2.GaussianBlur(ult, (35, 35), 0)
+ elif match == "negative":
+ ultroid = cv2.bitwise_not(ult)
+ elif match == "danger":
+ dan = cv2.cvtColor(ult, cv2.COLOR_BGR2RGB)
+ ultroid = cv2.cvtColor(dan, cv2.COLOR_HSV2BGR)
+ elif match == "mirror":
+ ish = cv2.flip(ult, 1)
+ ultroid = cv2.hconcat([ult, ish])
+ elif match == "flip":
+ trn = cv2.flip(ult, 1)
+ ish = cv2.rotate(trn, cv2.ROTATE_180)
+ ultroid = cv2.vconcat([ult, ish])
+ elif match == "quad":
+ ult = cv2.imread(file)
+ roid = cv2.flip(ult, 1)
+ mici = cv2.hconcat([ult, roid])
+ fr = cv2.flip(mici, 1)
+ trn = cv2.rotate(fr, cv2.ROTATE_180)
+ ultroid = cv2.vconcat([mici, trn])
+ elif match == "sketch":
+ gray_image = cv2.cvtColor(ult, cv2.COLOR_BGR2GRAY)
+ inverted_gray_image = 255 - gray_image
+ blurred_img = cv2.GaussianBlur(inverted_gray_image, (21, 21), 0)
+ inverted_blurred_img = 255 - blurred_img
+ ultroid = cv2.divide(gray_image, inverted_blurred_img, scale=256.0)
+ elif match == "toon":
+ height, width, _ = ult.shape
+ samples = np.zeros([height * width, 3], dtype=np.float32)
+ count = 0
+ for x in range(height):
+ for y in range(width):
+ samples[count] = ult[x][y]
+ count += 1
+ _, labels, centers = cv2.kmeans(
+ samples,
+ 12,
+ None,
+ (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10000, 0.0001),
+ 5,
+ cv2.KMEANS_PP_CENTERS,
+ )
+ centers = np.uint8(centers)
+ ish = centers[labels.flatten()]
+ ultroid = ish.reshape(ult.shape)
+ cv2.imwrite("ult.jpg", ultroid)
+ await ureply.reply(
+ file="ult.jpg",
+ force_document=False,
+ )
+ await xx.delete()
+ os.remove("ult.jpg")
+ os.remove(file)
+
+
+@ultroid_cmd(pattern="csample (.*)")
+async def sampl(ult):
+ if color := ult.pattern_match.group(1).strip():
+ img = Image.new("RGB", (200, 100), f"{color}")
+ img.save("csample.png")
+ try:
+ try:
+ await ult.delete()
+ await ult.respond(f"Colour Sample for `{color}` !", file="csample.png")
+ except MessageDeleteForbiddenError:
+ await ult.reply(f"Colour Sample for `{color}` !", file="csample.png")
+ except ChatSendMediaForbiddenError:
+ await ult.eor("Umm! Sending Media is disabled here!")
+
+ else:
+ await ult.eor("Wrong Color Name/Hex Code specified!")
+
+
+@ultroid_cmd(
+ pattern="blue$",
+)
+async def ultd(event):
+ ureply = await event.get_reply_message()
+ xx = await event.eor("`...`")
+ if not (ureply and (ureply.media)):
+ await xx.edit(get_string("cvt_3"))
+ return
+ ultt = await ureply.download_media()
+ if ultt.endswith(".tgs"):
+ await xx.edit(get_string("sts_9"))
+ file = await con.convert(ultt, convert_to="png", outname="ult")
+ got = upf(file)
+ lnk = f"https://graph.org{got[0]}"
+ r = await async_searcher(
+ f"https://nekobot.xyz/api/imagegen?type=blurpify&image={lnk}", re_json=True
+ )
+ ms = r.get("message")
+ if not r["success"]:
+ return await xx.edit(ms)
+ await download_file(ms, "ult.png")
+ img = Image.open("ult.png").convert("RGB")
+ img.save("ult.webp", "webp")
+ await event.client.send_file(
+ event.chat_id,
+ "ult.webp",
+ force_document=False,
+ reply_to=event.reply_to_msg_id,
+ )
+ await xx.delete()
+ os.remove("ult.png")
+ os.remove("ult.webp")
+ os.remove(ultt)
+
+
+@ultroid_cmd(pattern="border( (.*)|$)")
+async def ok(event):
+ hm = await event.get_reply_message()
+ if not (hm and (hm.photo or hm.sticker)):
+ return await event.eor("`Reply to Sticker or Photo..`")
+ col = event.pattern_match.group(1).strip()
+ wh = 20
+ if not col:
+ col = [255, 255, 255]
+ else:
+ try:
+ if ";" in col:
+ col_ = col.split(";", maxsplit=1)
+ wh = int(col_[1])
+ col = col_[0]
+ col = [int(col) for col in col.split(",")[:2]]
+ except ValueError:
+ return await event.eor("`Not a Valid Input...`")
+ okla = await hm.download_media()
+ img1 = cv2.imread(okla)
+ constant = cv2.copyMakeBorder(img1, wh, wh, wh, wh, cv2.BORDER_CONSTANT, value=col)
+ cv2.imwrite("output.png", constant)
+ await event.client.send_file(event.chat.id, "output.png")
+ os.remove("output.png")
+ os.remove(okla)
+ await event.delete()
+
+
+@ultroid_cmd(pattern="pixelator( (.*)|$)")
+async def pixelator(event):
+ reply_message = await event.get_reply_message()
+ if not (reply_message and (reply_message.photo or reply_message.sticker)):
+ return await event.eor("`Reply to a photo`")
+ hw = 50
+ try:
+ hw = int(event.pattern_match.group(1).strip())
+ except (ValueError, TypeError):
+ pass
+ msg = await event.eor(get_string("com_1"))
+ image = await reply_message.download_media()
+ input_ = cv2.imread(image)
+ height, width = input_.shape[:2]
+ w, h = (hw, hw)
+ temp = cv2.resize(input_, (w, h), interpolation=cv2.INTER_LINEAR)
+ output = cv2.resize(temp, (width, height), interpolation=cv2.INTER_NEAREST)
+ cv2.imwrite("output.jpg", output)
+ await msg.respond("• Pixelated by Ultroid", file="output.jpg")
+ await msg.delete()
+ os.remove("output.jpg")
+ os.remove(image)
diff --git a/plugins/imagine.py b/plugins/imagine.py
new file mode 100644
index 0000000000000000000000000000000000000000..7bbffcb7af7b0debd8257fb48f1e3fbe74b56797
--- /dev/null
+++ b/plugins/imagine.py
@@ -0,0 +1,80 @@
+from os import system, remove
+import json
+import requests
+import urllib.request
+import os
+from . import ultroid_cmd, udB, LOGS, run_async
+
+# Ensure the necessary library is installed
+try:
+ import requests
+except ImportError:
+ system("pip install requests")
+ import requests
+
+@run_async
+def generate_dalle_image(prompt, api_key):
+ url = "https://aiassistquizapp899573677638.openai.azure.com/openai/deployments/Dalle3/images/generations?api-version=2024-02-15-preview"
+ headers = {
+ "api-key": api_key,
+ "content-type": "application/json; charset=UTF-8",
+ "accept-encoding": "gzip",
+ "user-agent": "okhttp/4.10.0"
+ }
+ data = {
+ "response_format": "url",
+ "model": "dall-e-3",
+ "n": 1,
+ "prompt": prompt,
+ "size": "1024x1792"
+ }
+
+ response = requests.post(url, headers=headers, data=json.dumps(data))
+ if response.status_code == 200:
+ result = response.json()
+ return result["data"][0]
+ else:
+ return {"error": f"Error: {response.status_code} - {response.text}"}
+
+@ultroid_cmd(pattern="imagine(?: |$)(.*)")
+async def dalle_generator(event):
+ api_key = udB.get_key("DALL_E_API")
+ if not api_key:
+ return await event.eor("DALL_E_API key missing..")
+
+ query = event.pattern_match.group(1)
+ if not query:
+ reply = await event.get_reply_message()
+ if reply and reply.text:
+ query = reply.text
+ if not query:
+ return await event.eor("`need a prompt to generate image! `", time=6)
+
+ eris = await event.eor(f"__Generating image for:__\n`{query[:128]} ...`")
+
+ response = await generate_dalle_image(query, api_key)
+ if "error" in response:
+ await eris.edit(response["error"])
+ else:
+ image_url = response["url"]
+ revised_prompt = response.get("revised_prompt", "No revised prompt available.")
+ image_path = "generated_image.png"
+
+ try:
+ # Download the image
+ urllib.request.urlretrieve(image_url, image_path)
+
+ # Send the image
+ await event.client.send_file(
+ event.chat_id,
+ image_path,
+ caption=f"Model: • ([source]({image_url}))\n• $${revised_prompt}$$",
+ reply_to=event.id
+ )
+ await eris.delete()
+ except Exception as e:
+ await eris.edit(f"Failed to download or send image: {str(e)}")
+ finally:
+ # Remove the downloaded image after sending
+ if os.path.exists(image_path):
+ remove(image_path)
\ No newline at end of file
diff --git a/plugins/lastonult.py b/plugins/lastonult.py
new file mode 100644
index 0000000000000000000000000000000000000000..725113b93dd7b3a6073b215406a9f85703bcbecb
--- /dev/null
+++ b/plugins/lastonult.py
@@ -0,0 +1,387 @@
+"""
+❍ Commands Available -
+
+• `{i}lastonline`
+
+• `{i}seen `
+
+ 🌀 __@TrueSaiyan__ 🌀
+"""
+
+import html
+
+import motor.motor_asyncio
+import pytz
+from telethon import events, types
+from telethon.tl.functions.channels import GetParticipantsRequest
+from telethon.tl.types import (
+ ChannelParticipantsSearch,
+ User,
+ UserStatusOffline,
+ UserStatusOnline,
+ UserStatusRecently,
+)
+
+from . import *
+
+if udB.get_key("MONg"):
+ lastSeendB = udB.get_key("MONg")
+else:
+ lastSeendB = "mongodb+srv://LastSeenUlt:YKzBfhfjtObPfQLD@cluster0.iil65vg.mongodb.net/"
+
+# MongoDB client setup
+mongo_client = motor.motor_asyncio.AsyncIOMotorClient(lastSeendB)
+db = mongo_client["User_Status"]
+collection = db["user_data"]
+
+# Define the UTC timezone and Local timezone
+if udB.get_key("TIMEZONE"):
+ localTZ = udB.get_key("TIMEZONE")
+else:
+ localTZ = "Asia/Kolkata"
+
+utc_tz = pytz.utc
+perth_tz = pytz.timezone(localTZ)
+
+
+async def mention_user(user_id):
+ entity = await ultroid_bot.get_entity(user_id)
+ mention = get_display_name(entity)
+ escaped_mention = html.escape(mention)
+ permalink = f"{escaped_mention}"
+ return permalink
+
+
+async def get_group_members_last_online(event):
+ group = await event.client.get_entity(event.chat_id)
+ participants = await event.client(
+ GetParticipantsRequest(group, ChannelParticipantsSearch(""), 0, 25, hash=0)
+ )
+
+ users_currently_online = []
+ users_last_online = []
+ users_unknown_status = []
+
+ for user in participants.users:
+ if isinstance(user, User) and not user.bot:
+ user_status = user.status
+ user_id = user.id
+
+ if isinstance(user_status, UserStatusOffline):
+ was_online_utc = user_status.was_online.replace(tzinfo=utc_tz)
+ users_last_online.append((was_online_utc, user))
+ elif isinstance(user_status, UserStatusOnline):
+ users_currently_online.append(user)
+ else:
+ # Check the database for last seen data
+ db_user = await collection.find_one({"user_id": user_id})
+ if db_user:
+ last_online_db = db_user.get("last_online_time")
+ if last_online_db:
+ last_online_db = last_online_db.replace(tzinfo=utc_tz)
+ users_last_online.append((last_online_db, user))
+ else:
+ users_unknown_status.append(user)
+ else:
+ users_unknown_status.append(user)
+
+ users_last_online.sort(key=lambda x: x[0], reverse=True)
+
+ result = "Last Online Times for Group Members:\n\n"
+
+ for user in users_currently_online:
+ mention_text = await mention_user(user.id)
+ result += f"╭ User: {mention_text} ({user.id}
)\n"
+ result += f"⌬ Status: Currently online\n"
+ result += "╰──────────────\n\n"
+
+ for last_online_time, user in users_last_online:
+ mention_text = await mention_user(user.id)
+ last_online_perth = last_online_time.astimezone(perth_tz)
+ readable_time = last_online_perth.strftime("%d/%m/%Y %I:%M:%S %p %Z%z")
+ result += f"╭ User: {mention_text} ({user.id}
)\n"
+ result += f"⌬ Last Online: {readable_time}\n"
+ result += "╰──────────────\n\n"
+
+ for user in users_unknown_status:
+ mention_text = await mention_user(user.id)
+ result += f"╭ User: {mention_text} ({user.id}
)\n"
+ result += f"⌬ Status: Unknown or unsupported\n"
+ result += "╰──────────────\n\n"
+
+ return result
+
+
+@ultroid_cmd(pattern="lastonline$", manager=True)
+async def _(event):
+ xx = await event.eor(
+ "Fetching last online times for group members...", parse_mode="html"
+ )
+ try:
+ result = await get_group_members_last_online(event)
+ await xx.edit(result, parse_mode="html")
+ except Exception as er:
+ await xx.edit(f"ERROR : {er}")
+
+
+async def get_user_last_online(event, user_id):
+ user = await event.client.get_entity(user_id)
+ mention_text = await mention_user(user.id)
+
+ if not user.bot:
+ user_status = user.status
+
+ # Check the database for last seen data
+ db_user = await collection.find_one({"user_id": user.id})
+ if db_user:
+ first_seen = db_user.get("first_seen")
+ current_username = db_user.get("username")
+ last_online_db = db_user.get("last_online_time")
+ previous_usernames = db_user.get("previous_usernames", [])
+
+ if isinstance(user_status, UserStatusOffline) or isinstance(
+ user_status, UserStatusRecently
+ ):
+ if last_online_db:
+ last_online_db = last_online_db.replace(tzinfo=utc_tz).astimezone(
+ perth_tz
+ )
+ readable_last_online = last_online_db.strftime(
+ "%d/%m/%Y %I:%M:%S %p %Z%z"
+ )
+ if first_seen:
+ if user.id == 5575183435:
+ return (
+ f"User: {mention_text} ({user.id}
)\n"
+ f"⌬ First Seen: {first_seen}
\n"
+ f"⌬ Last Online: {readable_last_online}
\n"
+ f"⌬ Current Username: @{current_username}
"
+ )
+ first_seen = first_seen.replace(tzinfo=utc_tz).astimezone(
+ perth_tz
+ )
+ readable_first_seen = first_seen.strftime(
+ "%d/%m/%Y %I:%M:%S %p %Z%z"
+ )
+ if previous_usernames:
+ prev_usernames_text = ", @".join(previous_usernames)
+ return (
+ f"User: {mention_text} ({user.id}
)\n"
+ f"⌬ First Seen: {readable_first_seen}
\n"
+ f"⌬ Last Online: {readable_last_online}
\n"
+ f"⌬ Previous Usernames: @{prev_usernames_text}
"
+ )
+ return (
+ f"User: {mention_text} ({user.id}
)\n"
+ f"⌬ First Seen: {readable_first_seen}
\n"
+ f"⌬ Last Online: {readable_last_online}
\n"
+ f"⌬ Current Username: @{current_username}
"
+ )
+
+ if previous_usernames:
+ prev_usernames_text = ", @".join(previous_usernames)
+ return (
+ f"User: {mention_text} ({user.id}
)\n"
+ f"⌬ Last Online: {readable_last_online}
\n"
+ f"⌬ Previous Usernames: @{prev_usernames_text}
"
+ )
+ return (
+ f"User: {mention_text} ({user.id}
)\n"
+ f"⌬ Last Online: {readable_last_online}
\n"
+ f"⌬ Current Username: @{current_username}
"
+ )
+
+ elif isinstance(user_status, UserStatusOnline):
+ if previous_usernames:
+ prev_usernames_text = ", @".join(previous_usernames)
+ return (
+ f"User: {mention_text} ({user.id}
)\n"
+ f"⌬ Status: Currently online
\n"
+ f"⌬ Previous Usernames: @{prev_usernames_text}
"
+ )
+ return (
+ f"User: {mention_text} ({user.id}
)\n"
+ f"⌬ Status: Currently online
\n"
+ f"⌬ Current Username: @{current_username}
"
+ )
+
+ else:
+ try:
+ was_online_utc = user_status.was_online.replace(tzinfo=utc_tz)
+ was_online_perth = was_online_utc.astimezone(perth_tz)
+ readable_time = was_online_perth.strftime(
+ "%d/%m/%Y %I:%M:%S %p %Z%z"
+ )
+ if previous_usernames:
+ prev_usernames_text = ", @".join(previous_usernames)
+ return (
+ f"User: {mention_text} ({user.id}
)\n"
+ f"⌬ Last Online: {readable_time}
\n"
+ f"⌬ Previous Usernames: @{prev_usernames_text}
"
+ )
+ return (
+ f"User: {mention_text} ({user.id}
)\n"
+ f"⌬ Last Online: {readable_time}
\n"
+ f"⌬ Current Username: @{current_username}
"
+ )
+ except Exception:
+ if last_online_db:
+ last_online_db = last_online_db.replace(
+ tzinfo=utc_tz
+ ).astimezone(perth_tz)
+ readable_last_online = last_online_db.strftime(
+ "%d/%m/%Y %I:%M:%S %p %Z%z"
+ )
+ if first_seen:
+ first_seen = first_seen.replace(tzinfo=utc_tz).astimezone(
+ perth_tz
+ )
+ readable_first_seen = first_seen.strftime(
+ "%d/%m/%Y %I:%M:%S %p %Z%z"
+ )
+ if previous_usernames:
+ prev_usernames_text = ", @".join(previous_usernames)
+ return (
+ f"User: {mention_text} ({user.id}
)\n"
+ f"⌬ First Seen: {readable_first_seen}
\n"
+ f"⌬ Last Online: {readable_last_online}
\n"
+ f"⌬ Previous Usernames: @{prev_usernames_text}
"
+ )
+ return (
+ f"User: {mention_text} ({user.id}
)\n"
+ f"⌬ First Seen: {readable_first_seen}
\n"
+ f"⌬ Last Online: {readable_last_online}
\n"
+ f"⌬ Current Username: @{current_username}
"
+ )
+ if previous_usernames:
+ prev_usernames_text = ", @".join(previous_usernames)
+ return (
+ f"User: {mention_text} ({user.id}
)\n"
+ f"⌬ Last Online: {readable_last_online}
\n"
+ f"⌬ Previous Usernames: @{prev_usernames_text}
"
+ )
+ return (
+ f"User: {mention_text} ({user.id}
)\n"
+ f"⌬ Last Online: {readable_last_online}
\n"
+ f"⌬ Current Username: @{current_username}
"
+ )
+
+ return f"User: {mention_text} ({user.id}
)\n⌬ Status: Unknown or unsupported
"
+
+ else:
+ return f"User: {mention_text} ({user.id}
) is a bot and their status is not tracked."
+
+
+async def last_online_info(event, user_id):
+ user = await event.client.get_entity(user_id)
+ mention_text = inline_mention(user)
+
+ if not user.bot:
+ user.status
+
+ try:
+ db_user = await collection.find_one({"user_id": user.id})
+ if db_user:
+ db_user.get("first_seen")
+ last_online_db = db_user.get("last_online_time")
+ if last_online_db:
+ last_online_db = last_online_db.replace(tzinfo=utc_tz).astimezone(
+ perth_tz
+ )
+ readable_last_online = last_online_db.strftime(
+ "%d/%m/%Y %I:%M:%S %p %Z%z"
+ )
+ return f"{readable_last_online}"
+ return f"\n⌬ Status: Unknown or unsupported
"
+ except Exception as e:
+ LOGS.error(f"Error: {e}")
+ else:
+ return f"User: {mention_text} ({user.id}
) is a bot and their status is not tracked."
+
+
+@ultroid_cmd(pattern="seen(?: |$)(.*)", manager=True)
+async def _(event):
+ input_str = event.pattern_match.group(1)
+ xx = await event.eor("Fetching last online time...", parse_mode="html")
+
+ try:
+ if input_str:
+ if input_str.isdigit():
+ user_id = int(input_str)
+ result = await get_user_last_online(event, user_id)
+ await xx.edit(result, parse_mode="html")
+ else:
+ user = await event.client.get_entity(input_str)
+ result = await get_user_last_online(event, user.id)
+ await xx.edit(result, parse_mode="html")
+ else:
+ reply = await event.get_reply_message()
+ if reply and reply.sender_id:
+ result = await get_user_last_online(event, reply.sender_id)
+ await xx.edit(result, parse_mode="html")
+ else:
+ await xx.edit(
+ "Please specify a username or user ID or reply to a user's message to get their last online time."
+ )
+ except Exception as e:
+ await xx.edit(f"Error: {e}")
+
+
+@ultroid_bot.on(events.NewMessage(incoming=True))
+@ultroid_bot.on(events.ChatAction)
+async def all_messages_catcher(event):
+ if isinstance(event, events.NewMessage.Event):
+ sender = await event.get_sender()
+ utc_time = event.date.replace(tzinfo=utc_tz)
+ elif isinstance(event, events.ChatAction.Event):
+ utc_time = event.action_message.date.replace(tzinfo=utc_tz)
+ sender = await event.action_message.get_sender()
+ else:
+ return
+
+ if sender is None:
+ return
+
+ if isinstance(sender, types.User) and (sender.bot or sender.verified):
+ return
+
+
+ perth_time = utc_time.astimezone(perth_tz)
+
+ user_id = sender.id
+ username = sender.username or None
+
+ existing_user = await collection.find_one({"user_id": user_id})
+
+ if existing_user:
+ last_username = existing_user.get("username")
+
+ if last_username != username:
+ previous_usernames = existing_user.get("previous_usernames", [])
+ if last_username:
+ previous_usernames.append(last_username)
+
+ await collection.update_one(
+ {"user_id": user_id},
+ {
+ "$set": {
+ "last_online_time": perth_time,
+ "username": username,
+ "previous_usernames": previous_usernames,
+ }
+ },
+ )
+ else:
+ await collection.update_one(
+ {"user_id": user_id}, {"$set": {"last_online_time": perth_time}}
+ )
+ else:
+ await collection.insert_one(
+ {
+ "user_id": user_id,
+ "username": username,
+ "first_seen": perth_time,
+ "last_online_time": perth_time,
+ "previous_usernames": [],
+ }
+ )
\ No newline at end of file
diff --git a/plugins/lipsync.py b/plugins/lipsync.py
new file mode 100644
index 0000000000000000000000000000000000000000..14311573db19762c84ed8db25ee7972c683b10f1
--- /dev/null
+++ b/plugins/lipsync.py
@@ -0,0 +1,73 @@
+from os import remove
+from io import BytesIO
+import random
+
+try:
+ import requests
+except ImportError:
+ system("pip install -q requests")
+ import requests
+
+from . import ultroid_cmd, check_filename, fast_download, run_async, LOGS, async_searcher
+
+
+async def synthesize_lipsync(face_video_path, text):
+ url = "https://3v305hiwo6tem3-8888.proxy.runpod.net/synthesize"
+ headers = {
+ "User-Agent": "Dart/3.5 (dart:io)",
+ "Content-Type": "application/json",
+ "Accept-Encoding": "gzip",
+ }
+ data = {
+ "face": face_video_path,
+ "text": text,
+ "wav2lip_settings": {
+ "nosmooth": True,
+ "resize_factor": 2
+ },
+ "tts_settings": {
+ "voice_id": "LtPsVjX1k0Kl4StEMZPK"
+ }
+ }
+ response = await async_searcher(url, headers=headers, json=data, post=True, re_json=True)
+ return response
+
+@ultroid_cmd(pattern="lipsync( (.*)|$)")
+async def lipsync(event):
+ text = event.pattern_match.group(2)
+ reply = await event.get_reply_message()
+
+ if not text and reply and reply.text:
+ text = reply.text
+
+ if not text:
+ return await event.eor("Please provide the text to lip-sync.")
+
+ status_message = await event.eor("🔄 Processing lip-sync...")
+ face_video_path = None
+
+ if reply and reply.media:
+ await status_message.edit("📥 Downloading face video...")
+ face_video_path = await event.client.download_media(reply.media)
+ else:
+ # Generate a random number between 1 and 10 for the face video path
+ random_number = random.randint(1, 10)
+ face_video_path = f"characters/2aigo/lipsync/{random_number}.mp4"
+
+ try:
+ result = await synthesize_lipsync(face_video_path, text)
+ outfile_url = result.get('outfile')
+ if outfile_url:
+ await status_message.edit("📤 Uploading the result...")
+ result_file, _ = await fast_download(outfile_url, filename=check_filename("lipsynced_video.mp4"))
+ await event.client.send_file(event.chat_id, result_file, reply_to=event.reply_to_msg_id)
+ remove(result_file)
+ await status_message.delete()
+ else:
+ await status_message.edit("❌ Failed to generate the lip-synced video.")
+ except Exception as e:
+ LOGS.error(e, exc_info=True)
+ await status_message.edit(f"❌ An error occurred: {e}")
+ finally:
+ if face_video_path and not face_video_path.startswith("characters/2aigo/lipsync"):
+ remove(face_video_path)
\ No newline at end of file
diff --git a/plugins/locks.py b/plugins/locks.py
new file mode 100644
index 0000000000000000000000000000000000000000..849c242164be9a5b588b513a6d868742eeb51311
--- /dev/null
+++ b/plugins/locks.py
@@ -0,0 +1,39 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+"""
+✘ Commands Available -
+
+• `{i}lock `
+ Lock the Used Setting in Used Group.
+
+• `{i}unlock `
+ UNLOCK the Used Setting in Used Group.
+"""
+from telethon.tl.functions.messages import EditChatDefaultBannedRightsRequest
+
+from pyUltroid.fns.admins import lock_unlock
+
+from . import ultroid_cmd
+
+
+@ultroid_cmd(
+ pattern="(un|)lock( (.*)|$)", admins_only=True, manager=True, require="change_info"
+)
+async def un_lock(e):
+ mat = e.pattern_match.group(2).strip()
+ if not mat:
+ return await e.eor("`Give some Proper Input..`", time=5)
+ lock = e.pattern_match.group(1) == ""
+ ml = lock_unlock(mat, lock)
+ if not ml:
+ return await e.eor("`Incorrect Input`", time=5)
+ msg = "Locked" if lock else "Unlocked"
+ try:
+ await e.client(EditChatDefaultBannedRightsRequest(e.chat_id, ml))
+ except Exception as er:
+ return await e.eor(str(er))
+ await e.eor(f"**{msg}** - `{mat}` ! ")
diff --git a/plugins/logo.py b/plugins/logo.py
new file mode 100644
index 0000000000000000000000000000000000000000..92531bb1bf342597c0f3a9e1e4a12a1ce7cba95d
--- /dev/null
+++ b/plugins/logo.py
@@ -0,0 +1,101 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+"""
+✘ Commands Available -
+
+• `{i}logo `
+ Generate a logo of the given Text
+ Or Reply To image , to write ur text on it.
+ Or Reply To Font File, To write with that font.
+
+"""
+import glob
+import os
+import random
+
+from telethon.tl.types import InputMessagesFilterPhotos
+
+try:
+ from PIL import Image
+except ImportError:
+ Image = None
+from pyUltroid.fns.misc import unsplashsearch
+from pyUltroid.fns.tools import LogoHelper
+
+from . import OWNER_ID, OWNER_NAME, download_file, get_string, mediainfo, ultroid_cmd
+
+
+@ultroid_cmd(pattern="logo( (.*)|$)")
+async def logo_gen(event):
+ xx = await event.eor(get_string("com_1"))
+ name = event.pattern_match.group(1).strip()
+ if not name:
+ return await xx.eor("`Give a name too!`", time=5)
+ bg_, font_ = None, None
+ if event.reply_to_msg_id:
+ temp = await event.get_reply_message()
+ if temp.media:
+ if hasattr(temp.media, "document") and (
+ ("font" in temp.file.mime_type)
+ or (".ttf" in temp.file.name)
+ or (".otf" in temp.file.name)
+ ):
+ font_ = await temp.download_media("resources/fonts/")
+ elif "pic" in mediainfo(temp.media):
+ bg_ = await temp.download_media()
+ if not bg_:
+ SRCH = [
+ "background",
+ "neon",
+ "anime",
+ "art",
+ "bridges",
+ "streets",
+ "computer",
+ "cyberpunk",
+ "nature",
+ "abstract",
+ "exoplanet",
+ "magic",
+ "3d render",
+ ]
+ res = await unsplashsearch(random.choice(SRCH), limit=1)
+ bg_, _ = await download_file(res[0], "resources/downloads/logo.png")
+ newimg = "resources/downloads/unsplash-temp.jpg"
+ img_ = Image.open(bg_)
+ img_.save(newimg)
+ os.remove(bg_)
+ bg_ = newimg
+
+ if not font_:
+ fpath_ = glob.glob("resources/fonts/*")
+ font_ = random.choice(fpath_)
+ if len(name) <= 8:
+ strke = 10
+ elif len(name) >= 9:
+ strke = 5
+ else:
+ strke = 20
+ name = LogoHelper.make_logo(
+ bg_,
+ name,
+ font_,
+ fill="white",
+ stroke_width=strke,
+ stroke_fill="black",
+ )
+ await xx.edit("`Done!`")
+ await event.client.send_file(
+ event.chat_id,
+ file=name,
+ caption=f"Logo by [{OWNER_NAME}](tg://user?id={OWNER_ID})",
+ force_document=True,
+ )
+ os.remove(name)
+ await xx.delete()
+ if os.path.exists(bg_):
+ os.remove(bg_)
diff --git a/plugins/mediatools.py b/plugins/mediatools.py
new file mode 100644
index 0000000000000000000000000000000000000000..91773026da9ccf5e1d586cabd29d9c360d09b199
--- /dev/null
+++ b/plugins/mediatools.py
@@ -0,0 +1,146 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+"""
+✘ Commands Available -
+
+• `{i}mediainfo //`
+ To get info about it.
+
+• `{i}rotate `
+ Rotate any video/photo/media..
+ Note : for video it should be angle of 90's
+"""
+import os
+import time
+from datetime import datetime as dt
+
+from pyUltroid.fns.misc import rotate_image
+from pyUltroid.fns.tools import make_html_telegraph
+
+from . import (
+ LOGS,
+ Telegraph,
+ bash,
+ downloader,
+ get_string,
+ is_url_ok,
+ mediainfo,
+ ultroid_cmd,
+)
+
+try:
+ import cv2
+except ImportError:
+ LOGS.info("WARNING: 'cv2' not found!")
+ cv2 = None
+
+
+@ultroid_cmd(pattern="mediainfo( (.*)|$)")
+async def mi(e):
+ r = await e.get_reply_message()
+ match = e.pattern_match.group(1).strip()
+ taime = time.time()
+ extra = ""
+ if r and r.media:
+ xx = mediainfo(r.media)
+ murl = r.media.stringify()
+ url = await make_html_telegraph("Mediainfo", f"{murl}
")
+ extra = f"**[{xx}]({url})**\n\n"
+ e = await e.eor(f"{extra}`Loading More...`", link_preview=False)
+
+ if hasattr(r.media, "document"):
+ file = r.media.document
+ mime_type = file.mime_type
+ filename = r.file.name
+ if not filename:
+ if "audio" in mime_type:
+ filename = "audio_" + dt.now().isoformat("_", "seconds") + ".ogg"
+ elif "video" in mime_type:
+ filename = "video_" + dt.now().isoformat("_", "seconds") + ".mp4"
+ dl = await downloader(
+ f"resources/downloads/{filename}",
+ file,
+ e,
+ taime,
+ f"{extra}`Loading More...`",
+ )
+
+ naam = dl.name
+ else:
+ naam = await r.download_media()
+ elif match and (
+ os.path.isfile(match)
+ or (match.startswith("https://") and (await is_url_ok(match)))
+ ):
+ naam, xx = match, "file"
+ else:
+ return await e.eor(get_string("cvt_3"), time=5)
+ out, er = await bash(f"mediainfo '{naam}'")
+ if er:
+ LOGS.info(er)
+ out = extra or str(er)
+ return await e.edit(out, link_preview=False)
+ makehtml = ""
+ if naam.endswith((".jpg", ".png")):
+ if os.path.exists(naam):
+ med = "https://graph.org" + Telegraph.upload_file(naam)[0]["src"]
+ else:
+ med = match
+ makehtml += f"
"
+ for line in out.split("\n"):
+ line = line.strip()
+ if not line:
+ makehtml += "
"
+ elif ":" not in line:
+ makehtml += f"{line}
"
+ else:
+ makehtml += f"{line}
"
+ try:
+ urll = await make_html_telegraph("Mediainfo", makehtml)
+ except Exception as er:
+ LOGS.exception(er)
+ return
+ await e.eor(f"{extra}[{get_string('mdi_1')}]({urll})", link_preview=False)
+ if not match:
+ os.remove(naam)
+
+
+@ultroid_cmd(pattern="rotate( (.*)|$)")
+async def rotate_(ult):
+ match = ult.pattern_match.group(1).strip()
+ if not ult.is_reply:
+ return await ult.eor("`Reply to a media...`")
+ if match:
+ try:
+ match = int(match)
+ except ValueError:
+ match = None
+ if not match:
+ return await ult.eor("`Please provide a valid angle to rotate media..`")
+ reply = await ult.get_reply_message()
+ msg = await ult.eor(get_string("com_1"))
+ photo = reply.game.photo if reply.game else None
+ if reply.video:
+ media = await reply.download_media()
+ file = f"{media}.mp4"
+ await bash(
+ f'ffmpeg -i "{media}" -c copy -metadata:s:v:0 rotate={match} "{file}" -y'
+ )
+ elif photo or reply.photo or reply.sticker:
+ media = await ult.client.download_media(photo or reply)
+ img = cv2.imread(media)
+ new_ = rotate_image(img, match)
+ file = "ult.png"
+ cv2.imwrite(file, new_)
+ else:
+ return await msg.edit("`Unsupported Media..\nReply to Photo/Video`")
+ if os.path.exists(file):
+ await ult.client.send_file(
+ ult.chat_id, file=file, video_note=bool(reply.video_note), reply_to=reply.id
+ )
+ os.remove(media)
+ await msg.try_delete()
diff --git a/plugins/misc.py b/plugins/misc.py
new file mode 100644
index 0000000000000000000000000000000000000000..7a34a4ea6e1d2ebe64c530702053bc9b9189c3a3
--- /dev/null
+++ b/plugins/misc.py
@@ -0,0 +1,222 @@
+# Ultroid - UserBot
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+"""
+✘ Commands Available -
+
+• `{i}eod`
+ `Get Event of the Today`
+
+• `{i}pntrst `
+ Download and send pinterest pins
+
+• `{i}gadget `
+ Gadget Search from Telegram.
+
+• `{i}randomuser`
+ Generate details about a random user.
+
+• `{i}ascii `
+ Convert replied image into html.
+
+• `{i}igdl `
+ Download Instagram media
+"""
+
+import os
+from datetime import datetime as dt
+
+from bs4 import BeautifulSoup as bs
+
+from telethon import events
+from telethon.errors.rpcerrorlist import YouBlockedUserError
+from telethon.tl.types import DocumentAttributeVideo
+
+try:
+ from htmlwebshot import WebShot
+except ImportError:
+ WebShot = None
+try:
+ from img2html.converter import Img2HTMLConverter
+except ImportError:
+ Img2HTMLConverter = None
+
+from . import async_searcher, get_random_user_data, get_string, re, ultroid_cmd, eod
+
+
+async def get_gallery(msg_id):
+ msgs = await nimbus_bot.get_messages(
+ 5210630997, ids=[*range(msg_id - 9, msg_id + 10)]
+ )
+ return [msg for msg in msgs if msg and msg.grouped_id == msgs[9].grouped_id]
+
+@ultroid_cmd(pattern="igdl ?(.*)$")
+async def instagram(e):
+ listx = []
+ durations = []
+ resolutions = []
+ inp = e.pattern_match.group(1)
+ chat = "@TopSaverBot"
+ load = await e.eor(get_pstring("com_1"))
+ async with e.client.conversation(chat) as conv:
+ try:
+ response = conv.wait_event(
+ events.NewMessage(
+ incoming=True, from_users=5210630997, func=lambda e: e.media
+ )
+ )
+ await e.client.send_message(chat, f"{inp}")
+ response = await response
+ await e.client.send_read_acknowledge(conv.chat_id)
+ if inp.split("/")[3] == "p":
+ url = f"[Pᴏsᴛ]({inp})"
+ captions = get_pstring("instagram_1").format(url)
+ if inp.split("/")[3] == "reel":
+ url = f"[Rᴇᴇʟ]({inp})"
+ captions = get_pstring("instagram_1").format(url)
+ if inp.split("/")[3] == "stories":
+ url = f"[Sᴛᴏʀʏ]({inp})"
+ captions = get_pstring("instagram_1").format(url)
+ except YouBlockedUserError:
+ await load.eor("Please Unblock the bot...", time=4)
+ except Exception:
+ await load.eor("No media found...", time=4)
+
+ if response.grouped_id:
+ gallery_msgs = await get_gallery(response.id)
+ for msg in gallery_msgs:
+ media = msg.media
+ listx.append(media)
+ if media and hasattr(media.document, "attributes"):
+ for attribute in media.document.attributes:
+ if isinstance(attribute, DocumentAttributeVideo):
+ durations.append(int(attribute.duration))
+ resolutions.append(f"{attribute.w}x{attribute.h}")
+ else:
+ listx.append(response.media)
+ if response.media and hasattr(response.media.document, "attributes"):
+ for attribute in response.media.document.attributes:
+ if isinstance(attribute, DocumentAttributeVideo):
+ durations.append(int(attribute.duration))
+ resolutions.append(f"{attribute.w}x{attribute.h}")
+
+ if durations:
+ durations_str = ", ".join([f"{d}s" for d in durations])
+ captions += f"\n**Dᴜʀᴀᴛɪᴏɴs**: {durations_str}"
+ if resolutions:
+ resolutions_str = ", ".join(resolutions)
+ captions += f"\n**Rᴇsᴏʟᴜᴛɪᴏɴs**: {resolutions_str}"
+
+ try:
+ await e.client.send_file(
+ e.chat_id,
+ file=listx,
+ caption=captions,
+ )
+ await load.delete()
+ except Exception as er:
+ await e.eor(f"Unable to send media: {er}")
+
+
+
+@ultroid_cmd(pattern="eod$")
+async def diela(e):
+ m = await e.eor(get_string("com_1"))
+ li = "https://daysoftheyear.com"
+ te = "🎊 **Events of the Day**\n\n"
+ da = dt.now()
+ month = da.strftime("%b")
+ li += f"/days/{month}/" + da.strftime("%F").split("-")[2]
+ ct = await async_searcher(li, re_content=True)
+ bt = bs(ct, "html.parser", from_encoding="utf-8")
+ ml = bt.find_all("a", "js-link-target", href=re.compile("daysoftheyear.com/days"))
+ for eve in ml[:5]:
+ te += f'• [{eve.text}]({eve["href"]})\n'
+ await m.edit(te, link_preview=False)
+
+
+@ultroid_cmd(
+ pattern="pntrst( (.*)|$)",
+)
+async def pinterest(e):
+ m = e.pattern_match.group(1).strip()
+ if not m:
+ return await e.eor("`Give pinterest link.`", time=3)
+ soup = await async_searcher(
+ "https://www.expertstool.com/download-pinterest-video/",
+ data={"url": m},
+ post=True,
+ )
+ try:
+ _soup = bs(soup, "html.parser").find("table").tbody.find_all("tr")
+ except BaseException:
+ return await e.eor("`Wrong link or private pin.`", time=5)
+ file = _soup[1] if len(_soup) > 1 else _soup[0]
+ file = file.td.a["href"]
+ await e.client.send_file(e.chat_id, file, caption=f"Pin:- {m}")
+
+
+@ultroid_cmd(pattern="gadget( (.*)|$)")
+async def mobs(e):
+ mat = e.pattern_match.group(1).strip()
+ if not mat:
+ await e.eor("Please Give a Mobile Name to look for.")
+ query = mat.replace(" ", "%20")
+ jwala = f"https://gadgets.ndtv.com/search?searchtext={query}"
+ c = await async_searcher(jwala)
+ b = bs(c, "html.parser", from_encoding="utf-8")
+ co = b.find_all("div", "rvw-imgbox")
+ if not co:
+ return await e.eor("No Results Found!")
+ bt = await e.eor(get_string("com_1"))
+ out = "**📱 Mobile / Gadgets Search**\n\n"
+ li = co[0].find("a")
+ imu, title = None, li.find("img")["title"]
+ cont = await async_searcher(li["href"])
+ nu = bs(cont, "html.parser", from_encoding="utf-8")
+ req = nu.find_all("div", "_pdsd")
+ imu = nu.find_all(
+ "img", src=re.compile("https://i.gadgets360cdn.com/products/large/")
+ )
+ if imu:
+ imu = imu[0]["src"].split("?")[0] + "?downsize=*:420&output-quality=80"
+ out += f"☑️ **[{title}]({li['href']})**\n\n"
+ for fp in req:
+ ty = fp.findNext()
+ out += f"- **{ty.text}** - `{ty.findNext().text}`\n"
+ out += "_"
+ if imu == []:
+ imu = None
+ await e.reply(out, file=imu, link_preview=False)
+ await bt.delete()
+
+
+@ultroid_cmd(pattern="randomuser")
+async def _gen_data(event):
+ x = await event.eor(get_string("com_1"))
+ msg, pic = await get_random_user_data()
+ await event.reply(file=pic, message=msg)
+ await x.delete()
+
+
+@ultroid_cmd(
+ pattern="ascii( (.*)|$)",
+)
+async def _(e):
+ if not Img2HTMLConverter:
+ return await e.eor("'img2html-converter' not installed!")
+ if not e.reply_to_msg_id:
+ return await e.eor(get_string("ascii_1"))
+ m = await e.eor(get_string("ascii_2"))
+ img = await (await e.get_reply_message()).download_media()
+ char = e.pattern_match.group(1).strip() or "■"
+ converter = Img2HTMLConverter(char=char)
+ html = converter.convert(img)
+ shot = WebShot(quality=85)
+ pic = await shot.create_pic_async(html=html)
+ await m.delete()
+ await e.reply(file=pic)
+ os.remove(pic)
+ os.remove(img)
diff --git a/plugins/mute.py b/plugins/mute.py
new file mode 100644
index 0000000000000000000000000000000000000000..2939908fa0fb5959ef01ae54d345c1054a38ee4c
--- /dev/null
+++ b/plugins/mute.py
@@ -0,0 +1,210 @@
+# Ultroid - UserBot
+# Copyright (C) 2021-2023 TeamUltroid
+#
+# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
+# PLease read the GNU Affero General Public License in
+# .
+"""
+✘ Commands Available -
+
+• `{i}mute `
+ Mute user in current chat.
+
+• `{i}unmute `
+ Unmute user in current chat.
+
+• `{i}dmute `
+ Mute user in current chat by deleting msgs.
+
+• `{i}undmute `
+ Unmute dmuted user in current chat.
+
+• `{i}tmute