init, .gitignore

This commit is contained in:
2025-11-11 00:02:49 +01:00
commit 32aac89fdf
164 changed files with 18090 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
from asyncio import sleep
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
digits = {
str(i): el
for i, el in enumerate(["0️⃣", "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣"])
}
def prettify(val: int) -> str:
return "".join(digits[i] for i in str(val))
@Client.on_message(filters.command("ghoul", prefix) & filters.me)
async def ghoul_counter(_, message: Message):
await message.delete()
if len(message.command) > 1 and message.command[1].isdigit():
counter = int(message.command[1])
else:
counter = 1000
msg = await message.reply(prettify(counter), quote=False)
await sleep(1)
while counter // 7:
counter -= 7
await msg.edit(prettify(counter))
await sleep(1)
await msg.edit("<b>🤡 GHOUL 🤡</b>")
modules_help["1000-7"] = {
"ghoul [count_from]": "counting from 1000 (or given [count_from] to 0 as a ghoul"
}
+353
View File
@@ -0,0 +1,353 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from contextlib import suppress
from pyrogram.enums import ChatType
from pyrogram import Client, ContinuePropagation, filters
from pyrogram.errors import (
UserAdminInvalid,
ChatAdminRequired,
RPCError,
)
from pyrogram.raw import functions
from pyrogram.types import Message, ChatPermissions
from utils.db import db
from utils.scripts import format_exc, with_reply
from utils.misc import modules_help, prefix
from utils.handlers import (
BanHandler,
UnbanHandler,
KickHandler,
KickDeletedAccountsHandler,
TimeMuteHandler,
TimeUnmuteHandler,
TimeMuteUsersHandler,
UnmuteHandler,
MuteHandler,
DemoteHandler,
PromoteHandler,
AntiChannelsHandler,
DeleteHistoryHandler,
AntiRaidHandler,
)
db_cache: dict = db.get_collection("core.ats")
def update_cache():
db_cache.clear()
db_cache.update(db.get_collection("core.ats"))
@Client.on_message(filters.group & ~filters.me)
async def admintool_handler(_, message: Message):
if message.sender_chat and (
message.sender_chat.type == "supergroup"
or message.sender_chat.id == db_cache.get(f"linked{message.chat.id}", 0)
):
raise ContinuePropagation
if message.sender_chat and db_cache.get(f"antich{message.chat.id}", False):
with suppress(RPCError):
await message.delete()
await message.chat.ban_member(message.sender_chat.id)
tmuted_users = db_cache.get(f"c{message.chat.id}", [])
if (
message.from_user
and message.from_user.id in tmuted_users
or message.sender_chat
and message.sender_chat.id in tmuted_users
):
with suppress(RPCError):
await message.delete()
if db_cache.get(f"antiraid{message.chat.id}", False):
with suppress(RPCError):
await message.delete()
if message.from_user:
await message.chat.ban_member(message.from_user.id)
elif message.sender_chat:
await message.chat.ban_member(message.sender_chat.id)
if message.new_chat_members and db_cache.get(
f"welcome_enabled{message.chat.id}", False
):
await message.reply(
db_cache.get(f"welcome_text{message.chat.id}"),
disable_web_page_preview=True,
)
raise ContinuePropagation
async def get_user_and_name(message):
if message.reply_to_message.from_user:
return (
message.reply_to_message.from_user.id,
message.reply_to_message.from_user.first_name,
)
if message.reply_to_message.sender_chat:
return (
message.reply_to_message.sender_chat.id,
message.reply_to_message.sender_chat.title,
)
@Client.on_message(filters.command(["ban"], prefix) & filters.me)
async def ban_command(client: Client, message: Message):
handler = BanHandler(client, message)
await handler.handle_ban()
@Client.on_message(filters.command(["unban"], prefix) & filters.me)
async def unban_command(client: Client, message: Message):
handler = UnbanHandler(client, message)
await handler.handle_unban()
@Client.on_message(filters.command(["kick"], prefix) & filters.me)
async def kick_command(client: Client, message: Message):
handler = KickHandler(client, message)
await handler.handle_kick()
@Client.on_message(filters.command(["kickdel"], prefix) & filters.me)
async def kickdel_cmd(client: Client, message: Message):
handler = KickDeletedAccountsHandler(client, message)
await handler.kick_deleted_accounts()
@Client.on_message(filters.command(["tmute"], prefix) & filters.me)
async def tmute_command(client: Client, message: Message):
handler = TimeMuteHandler(client, message)
await handler.handle_tmute()
update_cache()
@Client.on_message(filters.command(["tunmute"], prefix) & filters.me)
async def tunmute_command(client: Client, message: Message):
handler = TimeUnmuteHandler(client, message)
await handler.handle_tunmute()
update_cache()
@Client.on_message(filters.command(["tmute_users"], prefix) & filters.me)
async def tunmute_users_command(client: Client, message: Message):
handler = TimeMuteUsersHandler(client, message)
await handler.list_tmuted_users()
@Client.on_message(filters.command(["unmute"], prefix) & filters.me)
async def unmute_command(client: Client, message: Message):
handler = UnmuteHandler(client, message)
await handler.handle_unmute()
@Client.on_message(filters.command(["mute"], prefix) & filters.me)
async def mute_command(client: Client, message: Message):
handler = MuteHandler(client, message)
await handler.handle_mute()
@Client.on_message(filters.command(["demote"], prefix) & filters.me)
async def demote_command(client: Client, message: Message):
handler = DemoteHandler(client, message)
await handler.handle_demote()
@Client.on_message(filters.command(["promote"], prefix) & filters.me)
async def promote_command(client: Client, message: Message):
handler = PromoteHandler(client, message)
await handler.handle_promote()
@Client.on_message(filters.command(["antich"], prefix))
async def anti_channels(client: Client, message: Message):
handler = AntiChannelsHandler(client, message)
await handler.handle_anti_channels()
update_cache()
@Client.on_message(filters.command(["delete_history", "dh"], prefix))
async def delete_history(client: Client, message: Message):
handler = DeleteHistoryHandler(client, message)
await handler.handle_delete_history()
@Client.on_message(filters.command(["report_spam", "rs"], prefix))
@with_reply
async def report_spam(client: Client, message: Message):
try:
channel = await client.resolve_peer(message.chat.id)
user_id, name = await get_user_and_name(message)
peer = await client.resolve_peer(user_id)
await client.invoke(
functions.channels.ReportSpam(
channel=channel,
participant=peer,
id=[message.reply_to_message.id],
)
)
except Exception as e:
await message.edit(format_exc(e))
else:
await message.edit(f"<b>Message</a> from {name} was reported</b>")
@Client.on_message(filters.command("pin", prefix) & filters.me)
@with_reply
async def pin(_, message: Message):
try:
await message.reply_to_message.pin()
await message.edit("<b>Pinned!</b>")
except Exception as e:
await message.edit(format_exc(e))
@Client.on_message(filters.command("unpin", prefix) & filters.me)
@with_reply
async def unpin(_, message: Message):
try:
await message.reply_to_message.unpin()
await message.edit("<b>Unpinned!</b>")
except Exception as e:
await message.edit(format_exc(e))
@Client.on_message(filters.command("ro", prefix) & filters.me)
async def ro(client: Client, message: Message):
if message.chat.type not in [ChatType.GROUP, ChatType.SUPERGROUP]:
await message.edit("<b>Invalid chat type</b>")
return
try:
perms = message.chat.permissions
perms_list = [
perms.can_send_messages,
perms.can_send_media_messages,
perms.can_send_polls,
perms.can_add_web_page_previews,
perms.can_change_info,
perms.can_invite_users,
perms.can_pin_messages,
]
db.set("core.ats", f"ro{message.chat.id}", perms_list)
try:
await client.set_chat_permissions(message.chat.id, ChatPermissions())
except (UserAdminInvalid, ChatAdminRequired):
await message.edit("<b>No rights</b>")
else:
await message.edit(
"<b>Read-only mode activated!\n"
f"Turn off with:</b><code>{prefix}unro</code>"
)
except Exception as e:
await message.edit(format_exc(e))
@Client.on_message(filters.command("unro", prefix) & filters.me)
async def unro(client: Client, message: Message):
if message.chat.type not in [ChatType.GROUP, ChatType.SUPERGROUP]:
await message.edit("<b>Invalid chat type</b>")
return
try:
perms_list = db.get(
"core.ats",
f"ro{message.chat.id}",
[True, True, False, False, False, False, False],
)
common_perms = {
"can_send_messages": perms_list[0],
"can_send_media_messages": perms_list[1],
"can_send_polls": perms_list[2],
"can_add_web_page_previews": perms_list[3],
"can_change_info": perms_list[4],
"can_invite_users": perms_list[5],
"can_pin_messages": perms_list[6],
}
perms = ChatPermissions(**common_perms)
try:
await client.set_chat_permissions(message.chat.id, perms)
except (UserAdminInvalid, ChatAdminRequired):
await message.edit("<b>No rights</b>")
else:
await message.edit("<b>Read-only mode disabled!</b>")
except Exception as e:
await message.edit(format_exc(e))
@Client.on_message(filters.command("antiraid", prefix) & filters.me)
async def antiraid(client: Client, message: Message):
handler = AntiRaidHandler(client, message)
await handler.handle_antiraid()
update_cache()
@Client.on_message(filters.command(["welcome", "wc"], prefix) & filters.me)
async def welcome(_, message: Message):
if message.chat.type not in [ChatType.GROUP, ChatType.SUPERGROUP]:
return await message.edit("<b>Unsupported chat type</b>")
if len(message.command) > 1:
text = message.text.split(maxsplit=1)[1]
db.set("core.ats", f"welcome_enabled{message.chat.id}", True)
db.set("core.ats", f"welcome_text{message.chat.id}", text)
await message.edit(
f"<b>Welcome enabled in this chat\nText:</b> <code>{text}</code>"
)
else:
db.set("core.ats", f"welcome_enabled{message.chat.id}", False)
await message.edit("<b>Welcome disabled in this chat</b>")
update_cache()
modules_help["admintool"] = {
"ban [reply]/[username/id]* [reason] [report_spam] [delete_history]": "ban user in chat",
"unban [reply]/[username/id]* [reason]": "unban user in chat",
"kick [reply]/[userid]* [reason] [report_spam] [delete_history]": "kick user out of chat",
"mute [reply]/[userid]* [reason] [1m]/[1h]/[1d]/[1w]": "mute user in chat",
"unmute [reply]/[userid]* [reason]": "unmute user in chat",
"promote [reply]/[userid]* [prefix]": "promote user in chat",
"demote [reply]/[userid]* [reason]": "demote user in chat",
"tmute [reply]/[username/id]* [reason]": "delete all new messages from user in chat",
"tunmute [reply]/[username/id]* [reason]": "stop deleting all messages from user in chat",
"tmute_users": "list of tmuted (.tmute) users",
"antich [enable/disable]": "turn on/off blocking channels in this chat",
"delete_history [reply]/[username/id]* [reason]": "delete history from member in chat",
"report_spam [reply]*": "report spam message in chat",
"pin [reply]*": "Pin replied message",
"unpin [reply]*": "Unpin replied message",
"ro": "enable read-only mode",
"unro": "disable read-only mode",
"antiraid [on|off]": "when enabled, anyone who writes message will be blocked. Useful in raids. "
"Running without arguments equals to toggling state",
"welcome [text]*": "enable auto-welcome to new users in groups. "
"Running without text equals to disable",
"kickdel": "Kick all deleted accounts",
}
+380
View File
@@ -0,0 +1,380 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from time import perf_counter
from typing import AsyncGenerator, List, Optional, Union
from pyrogram import Client, enums, filters, raw, types, utils
from pyrogram.types.object import Object
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
class Chat(Object):
def __init__(
self,
*,
client: "Client" = None,
id: id,
type: type,
is_verified: bool = None,
is_restricted: bool = None,
is_creator: bool = None,
is_scam: bool = None,
is_fake: bool = None,
is_support: bool = None,
title: str = None,
username: str = None,
first_name: str = None,
last_name: str = None,
photo: "types.ChatPhoto" = None,
bio: str = None,
description: str = None,
dc_id: int = None,
has_protected_content: bool = None,
invite_link: str = None,
pinned_message=None,
sticker_set_name: str = None,
can_set_sticker_set: bool = None,
members_count: int = None,
restrictions: List["types.Restriction"] = None,
permissions: "types.ChatPermissions" = None,
distance: int = None,
linked_chat: "types.Chat" = None,
send_as_chat: "types.Chat" = None,
available_reactions: Optional["types.ChatReactions"] = None,
is_admin: bool = False,
deactivated: bool = False,
):
super().__init__(client)
self.id = id
self.type = type
self.is_verified = is_verified
self.is_restricted = is_restricted
self.is_creator = is_creator
self.is_scam = is_scam
self.is_fake = is_fake
self.is_support = is_support
self.title = title
self.username = username
self.first_name = first_name
self.last_name = last_name
self.photo = photo
self.bio = bio
self.description = description
self.dc_id = dc_id
self.has_protected_content = has_protected_content
self.invite_link = invite_link
self.pinned_message = pinned_message
self.sticker_set_name = sticker_set_name
self.can_set_sticker_set = can_set_sticker_set
self.members_count = members_count
self.restrictions = restrictions
self.permissions = permissions
self.distance = distance
self.linked_chat = linked_chat
self.send_as_chat = send_as_chat
self.available_reactions = available_reactions
self.is_admin = is_admin
self.deactivated = deactivated
@staticmethod
def _parse_user_chat(client, user: raw.types.User) -> "Chat":
peer_id = user.id
return Chat(
id=peer_id,
type=enums.ChatType.BOT if user.bot else enums.ChatType.PRIVATE,
is_verified=getattr(user, "verified", None),
is_restricted=getattr(user, "restricted", None),
is_scam=getattr(user, "scam", None),
is_fake=getattr(user, "fake", None),
is_support=getattr(user, "support", None),
username=user.username,
first_name=user.first_name,
last_name=user.last_name,
photo=types.ChatPhoto._parse(client, user.photo, peer_id, user.access_hash),
restrictions=types.List(
[types.Restriction._parse(r) for r in user.restriction_reason]
)
or None,
dc_id=getattr(getattr(user, "photo", None), "dc_id", None),
client=client,
)
@staticmethod
def _parse_chat_chat(client, chat: raw.types.Chat) -> "Chat":
peer_id = -chat.id
return Chat(
id=peer_id,
type=enums.ChatType.GROUP,
title=chat.title,
is_creator=getattr(chat, "creator", None),
photo=types.ChatPhoto._parse(
client, getattr(chat, "photo", None), peer_id, 0
),
permissions=types.ChatPermissions._parse(
getattr(chat, "default_banned_rights", None)
),
members_count=getattr(chat, "participants_count", None),
dc_id=getattr(getattr(chat, "photo", None), "dc_id", None),
has_protected_content=getattr(chat, "noforwards", None),
client=client,
is_admin=bool(getattr(chat, "admin_rights", False)),
deactivated=chat.deactivated,
)
@staticmethod
def _parse_channel_chat(client, channel: raw.types.Channel) -> "Chat":
peer_id = utils.get_channel_id(channel.id)
restriction_reason = getattr(channel, "restriction_reason", [])
return Chat(
id=peer_id,
type=(
enums.ChatType.SUPERGROUP
if getattr(channel, "megagroup", None)
else enums.ChatType.CHANNEL
),
is_verified=getattr(channel, "verified", None),
is_restricted=getattr(channel, "restricted", None),
is_creator=getattr(channel, "creator", None),
is_scam=getattr(channel, "scam", None),
is_fake=getattr(channel, "fake", None),
title=channel.title,
username=getattr(channel, "username", None),
photo=types.ChatPhoto._parse(
client,
getattr(channel, "photo", None),
peer_id,
getattr(channel, "access_hash", 0),
),
restrictions=types.List(
[types.Restriction._parse(r) for r in restriction_reason]
)
or None,
permissions=types.ChatPermissions._parse(
getattr(channel, "default_banned_rights", None)
),
members_count=getattr(channel, "participants_count", None),
dc_id=getattr(getattr(channel, "photo", None), "dc_id", None),
has_protected_content=getattr(channel, "noforwards", None),
is_admin=bool(getattr(channel, "admin_rights", False)),
client=client,
)
@staticmethod
def _parse(
client,
message: Union[raw.types.Message, raw.types.MessageService],
users: dict,
chats: dict,
is_chat: bool,
) -> "Chat":
from_id = utils.get_raw_peer_id(message.from_id)
peer_id = utils.get_raw_peer_id(message.peer_id)
chat_id = (peer_id or from_id) if is_chat else (from_id or peer_id)
if isinstance(message.peer_id, raw.types.PeerUser):
return Chat._parse_user_chat(client, users[chat_id])
if isinstance(message.peer_id, raw.types.PeerChat):
return Chat._parse_chat_chat(client, chats[chat_id])
return Chat._parse_channel_chat(client, chats[chat_id])
@staticmethod
def _parse_dialog(client, peer, users: dict, chats: dict):
if isinstance(peer, raw.types.PeerUser):
return Chat._parse_user_chat(client, users[peer.user_id])
if isinstance(peer, raw.types.PeerChat):
return Chat._parse_chat_chat(client, chats[peer.chat_id])
return Chat._parse_channel_chat(client, chats[peer.channel_id])
class Dialog(Object):
def __init__(
self,
*,
client: "Client" = None,
chat: "types.Chat",
top_message: "types.Message",
unread_messages_count: int,
unread_mentions_count: int,
unread_mark: bool,
is_pinned: bool,
):
super().__init__(client)
self.chat = chat
self.top_message = top_message
self.unread_messages_count = unread_messages_count
self.unread_mentions_count = unread_mentions_count
self.unread_mark = unread_mark
self.is_pinned = is_pinned
@staticmethod
def _parse(client, dialog: "raw.types.Dialog", messages, users, chats) -> "Dialog":
return Dialog(
chat=Chat._parse_dialog(client, dialog.peer, users, chats),
top_message=messages.get(utils.get_peer_id(dialog.peer)),
unread_messages_count=dialog.unread_count,
unread_mentions_count=dialog.unread_mentions_count,
unread_mark=dialog.unread_mark,
is_pinned=dialog.pinned,
client=client,
)
async def get_dialogs(
self: "Client", limit: int = 0
) -> Optional[AsyncGenerator["types.Dialog", None]]:
current = 0
total = limit or (1 << 31) - 1
limit = min(100, total)
offset_date = 0
offset_id = 0
offset_peer = raw.types.InputPeerEmpty()
while True:
r = await self.invoke(
raw.functions.messages.GetDialogs(
offset_date=offset_date,
offset_id=offset_id,
offset_peer=offset_peer,
limit=limit,
hash=0,
),
sleep_threshold=60,
)
users = {i.id: i for i in r.users}
chats = {i.id: i for i in r.chats}
messages = {}
for message in r.messages:
if isinstance(message, raw.types.MessageEmpty):
continue
chat_id = utils.get_peer_id(message.peer_id)
messages[chat_id] = await types.Message._parse(self, message, users, chats)
dialogs = []
for dialog in r.dialogs:
if not isinstance(dialog, raw.types.Dialog):
continue
dialogs.append(Dialog._parse(self, dialog, messages, users, chats))
if not dialogs:
return
last = dialogs[-1]
offset_id = last.top_message.id
offset_date = utils.datetime_to_timestamp(last.top_message.date)
offset_peer = await self.resolve_peer(last.chat.id)
for dialog in dialogs:
yield dialog
current += 1
if current >= total:
return
@Client.on_message(filters.command("admlist", prefix) & filters.me)
async def admlist(client: Client, message: types.Message):
await message.edit("<b>Retrieving information... (it'll take some time)</b>")
start = perf_counter()
try:
adminned_chats = []
owned_chats = []
owned_usernamed_chats = []
async for dialog in get_dialogs(client):
chat = dialog.chat
if getattr(chat, "deactivated", False):
continue
if getattr(chat, "is_creator", False) and getattr(chat, "username", None):
owned_usernamed_chats.append(chat)
elif getattr(chat, "is_creator", False):
owned_chats.append(chat)
elif getattr(chat, "is_admin", False):
adminned_chats.append(chat)
text = "<b>Adminned chats:</b>\n"
for index, chat in enumerate(adminned_chats):
cid = str(chat.id).replace("-100", "")
text += f"{index + 1}. <a href=https://t.me/c/{cid}/1>{chat.title}</a>\n"
text += "\n<b>Owned chats:</b>\n"
for index, chat in enumerate(owned_chats):
cid = str(chat.id).replace("-100", "")
text += f"{index + 1}. <a href=https://t.me/c/{cid}/1>{chat.title}</a>\n"
text += "\n<b>Owned chats with username:</b>\n"
for index, chat in enumerate(owned_usernamed_chats):
cid = str(chat.id).replace("-100", "")
text += f"{index + 1}. <a href=https://t.me/c/{cid}/1>{chat.title}</a>\n"
stop = perf_counter()
total_count = (
len(adminned_chats) + len(owned_chats) + len(owned_usernamed_chats)
)
await message.edit(
text + "\n"
f"<b><u>Total:</u></b> {total_count}"
f"\n<b><u>Adminned chats:</u></b> {len(adminned_chats)}\n"
f"<b><u>Owned chats:</u></b> {len(owned_chats)}\n"
f"<b><u>Owned chats with username:</u></b> {len(owned_usernamed_chats)}\n\n"
f"Done in {round(stop - start, 3)} seconds.",
)
except Exception as e:
await message.edit(format_exc(e))
return
@Client.on_message(filters.command("admcount", prefix) & filters.me)
async def admcount(client: Client, message: types.Message):
await message.edit("<b>Retrieving information... (it'll take some time)</b>")
start = perf_counter()
try:
adminned_chats = 0
owned_chats = 0
owned_usernamed_chats = 0
async for dialog in get_dialogs(client):
chat = dialog.chat
if getattr(chat, "deactivated", False):
continue
if getattr(chat, "is_creator", False) and getattr(chat, "username", None):
owned_usernamed_chats += 1
elif getattr(chat, "is_creator", False):
owned_chats += 1
elif getattr(chat, "is_admin", False):
adminned_chats += 1
stop = perf_counter()
total_count = adminned_chats + owned_chats + owned_usernamed_chats
await message.edit(
f"<b><u>Total:</u></b> {total_count}"
f"\n<b><u>Adminned chats:</u></b> {adminned_chats}\n"
f"<b><u>Owned chats:</u></b> {owned_chats}\n"
f"<b><u>Owned chats with username:</u></b> {owned_usernamed_chats}\n\n"
f"Done in {round(stop - start, 3)} seconds.\n\n"
f"<b>Get full list: </b><code>{prefix}admlist</code>",
)
except Exception as e:
await message.edit(format_exc(e))
return
modules_help["admlist"] = {
"admcount": "Get count of adminned and owned chats",
"admlist": "Get list of adminned and owned chats",
}
+88
View File
@@ -0,0 +1,88 @@
# Dragon-Userbot - telegram userbot
# Copyright (C) 2020-present Dragon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import datetime
from pyrogram import Client, filters, types
from utils.db import db
from utils.misc import modules_help, prefix
# avoid using global variables
afk_info = db.get(
"core.afk",
"afk_info",
{
"start": 0,
"is_afk": False,
"reason": "",
},
)
is_afk = filters.create(lambda _, __, ___: afk_info["is_afk"])
is_support = filters.create(lambda _, __, message: message.chat.is_support)
@Client.on_message(
is_afk
& (filters.private | filters.mentioned)
& ~filters.channel
& ~filters.me
& ~filters.bot
& ~is_support
)
async def afk_handler(_, message: types.Message):
start = datetime.datetime.fromtimestamp(afk_info["start"])
end = datetime.datetime.now().replace(microsecond=0)
afk_time = end - start
await message.reply(
f"<b>I'm AFK {afk_time}\nReason:</b> <i>{afk_info['reason']}</i>"
)
@Client.on_message(filters.command("afk", prefix) & filters.me)
async def afk(_, message):
if len(message.text.split()) >= 2:
reason = message.text.split(" ", maxsplit=1)[1]
else:
reason = "None"
afk_info["start"] = int(datetime.datetime.now().timestamp())
afk_info["is_afk"] = True
afk_info["reason"] = reason
await message.edit(f"<b>I'm going AFK.\n" f"Reason:</b> <i>{reason}</i>")
db.set("core.afk", "afk_info", afk_info)
@Client.on_message(filters.command("unafk", prefix) & filters.me)
async def unafk(_, message):
if afk_info["is_afk"]:
start = datetime.datetime.fromtimestamp(afk_info["start"])
end = datetime.datetime.now().replace(microsecond=0)
afk_time = end - start
await message.edit(
f"<b>I'm not AFK anymore.\n" f"I was afk {afk_time}</b>"
)
afk_info["is_afk"] = False
else:
await message.edit("<b>You weren't afk</b>")
db.set("core.afk", "afk_info", afk_info)
modules_help["afk"] = {"afk [reason]": "Go to afk", "unafk": "Get out of AFK"}
+129
View File
@@ -0,0 +1,129 @@
import os
from PIL import Image
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_exc, import_library
genai = import_library("google.generativeai", "google-generativeai")
from utils.config import gemini_key
genai.configure(api_key=gemini_key)
generation_config_cook = {
"temperature": 0.35,
"top_p": 0.95,
"top_k": 40,
"max_output_tokens": 1024,
}
model = genai.GenerativeModel("gemini-1.5-flash-latest")
model_cook = genai.GenerativeModel(
model_name="gemini-1.5-flash-latest", generation_config=generation_config_cook
)
@Client.on_message(filters.command("getai", prefix) & filters.me)
async def getai(_, message: Message):
try:
await message.edit_text("<code>Please Wait...</code>")
try:
base_img = await message.reply_to_message.download()
except AttributeError:
return await message.edit_text("<code>Please reply to an image...</code>")
img = Image.open(base_img)
prompt = "Get details of given image, be as accurate as possible."
response = model.generate_content([prompt, img])
await message.edit_text(
f"**Detail Of Image:** {response.text}", parse_mode=enums.ParseMode.MARKDOWN
)
os.remove(base_img)
return
except Exception as e:
await message.edit_text(f"An error occurred: {format_exc(e)}")
@Client.on_message(filters.command("aicook", prefix) & filters.me)
async def aicook(_, message: Message):
if message.reply_to_message:
try:
await message.edit_text("<code>Cooking...</code>")
try:
base_img = await message.reply_to_message.download()
except AttributeError:
return await message.edit_text(
"<code>Please reply to an image...</code>"
)
img = Image.open(base_img)
cook_img = [
"Accurately identify the baked good in the image and provide an appropriate and recipe consistent with your analysis. ",
img,
]
response = model_cook.generate_content(cook_img)
await message.edit_text(
f"{response.text}", parse_mode=enums.ParseMode.MARKDOWN
)
os.remove(base_img)
return
except Exception as e:
await message.edit_text(str(e))
return await message.edit_text("<code>Please reply to an image...</code>")
@Client.on_message(filters.command("aiseller", prefix) & filters.me)
async def aiseller(_, message: Message):
if message.reply_to_message:
try:
await message.edit_text("<code>Generating...</code>")
if len(message.command) > 1:
taud = message.text.split(maxsplit=1)[1]
else:
return await message.edit_text(
f"<b>Usage: </b><code>{prefix}aiseller [target audience] [reply to product image]</code>"
)
try:
base_img = await message.reply_to_message.download()
except AttributeError:
return await message.edit_text(
"<code>Please reply to an image...</code>"
)
img = Image.open(base_img)
sell_img = [
"Given an image of a product and its target audience, write an engaging marketing description",
"Product Image: ",
img,
"Target Audience: ",
taud,
]
response = model.generate_content(sell_img)
await message.edit_text(
f"{response.text}", parse_mode=enums.ParseMode.MARKDOWN
)
os.remove(base_img)
return
except Exception:
await message.edit_text(
f"<b>Usage: </b><code>{prefix}aiseller [target audience] [reply to product image]</code>"
)
return await message.edit_text("<code>Please reply to an image...</code>")
modules_help["aimage"] = {
"getai [reply to image]*": "Get details of image with Ai",
"aicook [reply to image]*": "Generate Cooking instrunctions of the given food image",
"aiseller [target audience] [reply to product image]*": "Generate a promotional message for the given image product for the given target audience",
}
+58
View File
@@ -0,0 +1,58 @@
from io import BytesIO
from random import randint
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from requests import get
from PIL import Image, ImageFont, ImageDraw
from textwrap import wrap
from utils.misc import modules_help, prefix
@Client.on_message(filters.command("amogus", prefix) & filters.me)
async def amogus(client: Client, message: Message):
text = " ".join(message.command[1:])
await message.edit(
"<b>amgus, tun tun tun tun tun tun tun tudududn tun tun...</b>",
parse_mode=enums.ParseMode.HTML,
)
clr = randint(1, 12)
url = "https://raw.githubusercontent.com/The-MoonTg-project/AmongUs/master/"
font = ImageFont.truetype(BytesIO(get(url + "bold.ttf").content), 60)
imposter = Image.open(BytesIO(get(f"{url}{clr}.png").content))
text_ = "\n".join(["\n".join(wrap(part, 30)) for part in text.split("\n")])
bbox = ImageDraw.Draw(Image.new("RGB", (1, 1))).multiline_textbbox(
(0, 0), text_, font, stroke_width=2
)
# w, h = bbox[2] - bbox[0], bbox[3] - bbox[1]
w, h = bbox[2], bbox[3]
text = Image.new("RGBA", (w + 30, h + 30))
ImageDraw.Draw(text).multiline_text(
(15, 15), text_, "#FFF", font, stroke_width=2, stroke_fill="#000"
)
w = imposter.width + text.width + 10
h = max(imposter.height, text.height)
image = Image.new("RGBA", (w, h))
image.paste(imposter, (0, h - imposter.height), imposter)
image.paste(text, (w - text.width, 0), text)
image.thumbnail((512, 512))
output = BytesIO()
output.name = "imposter.webp"
image.save(output)
output.seek(0)
await message.delete()
await client.send_sticker(message.chat.id, output)
modules_help["amogus"] = {
"amogus [text]": "amgus, tun tun tun tun tun tun tun tudududn tun tun"
}
+218
View File
@@ -0,0 +1,218 @@
# From CatUB
import asyncio
import re
from io import BytesIO
from random import choice, randint
from textwrap import wrap
from PIL import Image, ImageDraw, ImageFont
from click import edit
import requests
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from utils.scripts import edit_or_reply, ReplyCheck
from utils.misc import modules_help, prefix
async def amongus_gen(text: str, clr: int) -> str:
url = (
"https://github.com/TgCatUB/CatUserbot-Resources/raw/master/Resources/Amongus/"
)
font = ImageFont.truetype(
BytesIO(
requests.get(
"https://github.com/TgCatUB/CatUserbot-Resources/raw/master/Resources/fonts/bold.ttf"
).content
),
60,
)
imposter = Image.open(BytesIO(requests.get(f"{url}{clr}.png").content))
text_ = "\n".join("\n".join(wrap(part, 30)) for part in text.split("\n"))
bbox = ImageDraw.Draw(Image.new("RGB", (1, 1))).multiline_textbbox(
(0, 0), text_, font, stroke_width=2
)
w, h = bbox[2], bbox[3]
text = Image.new("RGBA", (w + 30, h + 30))
ImageDraw.Draw(text).multiline_text(
(15, 15), text_, "#FFF", font, stroke_width=2, stroke_fill="#000"
)
w = imposter.width + text.width + 10
h = max(imposter.height, text.height)
image = Image.new("RGBA", (w, h))
image.paste(imposter, (0, h - imposter.height), imposter)
image.paste(text, (w - text.width, 0), text)
image.thumbnail((512, 512))
output = BytesIO()
output.name = "imposter.webp"
image.save(output, "WebP")
output.seek(0)
return output
async def get_imposter_img(text: str) -> BytesIO:
background = requests.get(
f"https://github.com/TgCatUB/CatUserbot-Resources/raw/master/Resources/imposter/impostor{randint(1, 22)}.png"
).content
font = requests.get(
"https://github.com/TgCatUB/CatUserbot-Resources/raw/master/Resources/fonts/roboto_regular.ttf"
).content
font = BytesIO(font)
font = ImageFont.truetype(font, 30)
image = Image.new("RGBA", (1, 1), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
bbox = ImageDraw.Draw(Image.new("RGB", (1, 1))).multiline_textbbox(
(0, 0), text, font, stroke_width=2
)
w, h = bbox[2], bbox[3]
image = Image.open(BytesIO(background))
x, y = image.size
draw = ImageDraw.Draw(image)
draw.multiline_text(
((x - w) // 2, (y - h) // 2), text=text, font=font, fill="white", align="center"
)
output = BytesIO()
output.name = "impostor.png"
image.save(output, "PNG")
output.seek(0)
return output
@Client.on_message(filters.command("amongus", prefix) & filters.me)
async def amongus_cmd(client: Client, message: Message):
text = " ".join(message.command[1:]) if len(message.command) > 1 else ""
reply = message.reply_to_message
await message.edit("tun tun tun...")
if not text and reply:
text = reply.text or reply.caption or ""
clr = re.findall(r"-c\d+", text)
try:
clr = clr[0]
clr = clr.replace("-c", "")
text = text.replace(f"-c{clr}", "")
clr = int(clr)
if clr > 12 or clr < 1:
clr = randint(1, 12)
except IndexError:
clr = randint(1, 12)
if not text:
if not reply:
text = f"{message.from_user.first_name} Was a traitor!"
else:
text = f"{reply.from_user.first_name} Was a traitor!"
imposter_file = await amongus_gen(text, clr)
await message.delete()
await client.send_sticker(
message.chat.id,
imposter_file,
reply_to_message_id=ReplyCheck(message),
)
@Client.on_message(filters.command("imposter", prefix) & filters.me)
async def imposter_cmd(client: Client, message: Message):
remain = randint(1, 2)
imps = ["wasn't the impostor", "was the impostor"]
if message.reply_to_message:
user = message.reply_to_message.from_user
text = f"{user.first_name} {choice(imps)}."
else:
args = message.text.split()[1:]
if args:
text = " ".join(args)
else:
text = f"{message.from_user.first_name} {choice(imps)}."
text += f"\n{remain} impostor(s) remain."
imposter_file = await get_imposter_img(text)
await message.delete()
await client.send_photo(
message.chat.id,
imposter_file,
reply_to_message_id=ReplyCheck(message),
)
@Client.on_message(filters.command(["imp", "impn"], prefix) & filters.me)
async def imp_animation(client: Client, message: Message):
name = " ".join(message.command[1:]) if len(message.command) > 1 else ""
if not name:
reply = message.reply_to_message
if reply:
name = reply.from_user.first_name
else:
name = message.from_user.first_name
cmd = message.command[0].lower()
text1 = await edit_or_reply(message, "Uhmm... Something is wrong here!!")
await asyncio.sleep(2)
await text1.delete()
stcr1 = await client.send_sticker(message.chat.id, "CAADAQADRwADnjOcH98isYD5RJTwAg")
text2 = await message.reply(
f"<b>{message.from_user.first_name}:</b> I have to call discussion"
)
await asyncio.sleep(3)
await stcr1.delete()
await text2.delete()
stcr2 = await client.send_sticker(message.chat.id, "CAADAQADRgADnjOcH9odHIXtfgmvAg")
text3 = await message.reply(
f"<b>{message.from_user.first_name}:</b> We have to eject the imposter or will lose"
)
await asyncio.sleep(3)
await stcr2.delete()
await text3.delete()
stcr3 = await client.send_sticker(message.chat.id, "CAADAQADOwADnjOcH77v3Ap51R7gAg")
text4 = await message.reply("<b>Others:</b> Where???")
await asyncio.sleep(2)
await text4.edit("<b>Others:</b> Who??")
await asyncio.sleep(2)
await text4.edit(
f"<b>{message.from_user.first_name}:</b> Its {name}, I saw {name} using vent"
)
await asyncio.sleep(3)
await text4.edit(f"<b>Others:</b> Okay.. Vote {name}")
await asyncio.sleep(2)
await stcr3.delete()
await text4.delete()
stcr4 = await client.send_sticker(message.chat.id, "CAADAQADLwADnjOcH-wxu-ehy6NRAg")
event = await message.reply(f"{name} is ejected.......")
# Ejection animation
for _ in range(9):
await asyncio.sleep(0.5)
curr_pos = _ + 1
spaces_before = "" * curr_pos
await event.edit(f"{spaces_before}{'' * (9 - curr_pos)}")
await asyncio.sleep(0.5)
await event.edit("")
await asyncio.sleep(0.2)
await stcr4.delete()
if cmd == "imp":
text = f".    。    •   ゚  。   .\n .      .     。   。 .  \n\n .    。   ඞ 。 .    •     •\n\n{name} was an Imposter. 。 .     。 . 。 . \n  . 。   . \n ' 0 Impostor remains   。 .   . 。 . 。   . 。   . . . , 。\n  ゚   .  . ,   。   .   . 。"
sticker_id = "CAADAQADLQADnjOcH39IqwyR6Q_0Ag"
else:
text = f".    。    •   ゚  。   .\n .      .     。   。 .  \n\n .    。   ඞ 。 .    •     •\n\n{name} was not an Imposter. 。 .     。 . 。 . \n  . 。   . \n ' 1 Impostor remains   。 .   . 。 . 。   . 。   . . . , 。\n  ゚   .  . ,   。   .   . 。"
sticker_id = "CAADAQADQAADnjOcH-WOkB8DEctJAg"
await event.edit(text)
await asyncio.sleep(4)
await event.delete()
await client.send_sticker(message.chat.id, sticker_id)
modules_help["amongus"] = {
"amongus": "Create Among Us themed sticker [text/reply] [-c1 to -c12 for colors]",
"imposter": "Create Among Us imposter image [username/reply]",
"imp": "Create Among Us ejection animation (imposter)",
"impn": "Create Among Us ejection animation (not imposter)",
}
File diff suppressed because one or more lines are too long
+243
View File
@@ -0,0 +1,243 @@
import os
import requests
import aiofiles
from pyrogram import Client, filters, enums
from pyrogram.types import Message, InputMediaPhoto
from pyrogram.errors import MediaCaptionTooLong
from utils.misc import prefix, modules_help
from utils.scripts import format_exc
url = "https://api.safone.co"
headers = {
"Accept-Language": "en-US,en;q=0.9",
"Connection": "keep-alive",
"DNT": "1",
"Referer": "https://api.safone.co/docs",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"accept": "application/json",
"sec-ch-ua": '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Linux"',
}
@Client.on_message(filters.command("anime_search", prefix) & filters.me)
async def anime_search(client: Client, message: Message):
try:
chat_id = message.chat.id
await message.edit_text("Processing...")
if len(message.command) > 1:
query = message.text.split(maxsplit=1)[1]
else:
message.edit_text(
"What should i search? You didn't provided me with any value to search"
)
response = requests.get(
url=f"{url}/anime/search?query={query}", headers=headers, timeout=5
)
if response.status_code != 200:
await message.edit_text("Something went wrong")
return
result = response.json()
averageScore = result["averageScore"]
try:
coverImage_url = result["imageUrl"]
coverImage = requests.get(url=coverImage_url).content
async with aiofiles.open("coverImage.jpg", mode="wb") as f:
await f.write(coverImage)
except Exception:
coverImage = None
title = result["title"]["english"]
trailer = result["trailer"]["id"]
description = result["description"]
episodes = result["episodes"]
genres = ", ".join(result["genres"])
isAdult = result["isAdult"]
status = result["status"]
studios = ", ".join(result["studios"])
await message.delete()
await client.send_media_group(
chat_id,
[
InputMediaPhoto(
"coverImage.jpg",
caption=f"<b>Title:</b> <code>{title}</code>\n<b>Average Score:</b> <code>{averageScore}</code>\n<b>Status:</b> <code>{status}</code>\n<b>Genres:</b> <code>{genres}</code>\n<b>Episodes:</b> <code>{episodes}</code>\n<b>Is Adult:</b> <code>{isAdult}</code>\n<b>Studios:</b> <code>{studios}</code>\n<b>Description:</b> <code>{description}</code>\n<b>Trailer:</b> <a href='https://youtu.be/{trailer}'>Click Here</a>",
)
],
)
except MediaCaptionTooLong:
description = description[:850]
await message.delete()
await client.send_media_group(
chat_id,
[
InputMediaPhoto(
"coverImage.jpg",
caption=f"<b>Title:</b> <code>{title}</code>\n<b>Average Score:</b> <code>{averageScore}</code>\n<b>Status:</b> <code>{status}</code>\n<b>Genres:</b> <code>{genres}</code>\n<b>Episodes:</b> <code>{episodes}</code>\n<b>Is Adult:</b> <code>{isAdult}</code>\n<b>Studios:</b> <code>{studios}</code>\n<b>Description:</b> <code>{description}</code>\n<b>Trailer:</b> <a href='https://youtu.be/{trailer}'>Click Here</a>",
)
],
)
except Exception as e:
await message.edit_text(format_exc(e))
finally:
if os.path.exists("coverImage.jpg"):
os.remove("coverImage.jpg")
@Client.on_message(filters.command("manga_search", prefix) & filters.me)
async def manga_search(client: Client, message: Message):
try:
chat_id = message.chat.id
await message.edit_text("Processing...")
if len(message.command) > 1:
query = message.text.split(maxsplit=1)[1]
else:
message.edit_text(
"What should i search? You didn't provided me with any value to search"
)
response = requests.get(
url=f"{url}/anime/manga?query={query}", headers=headers, timeout=5
)
if response.status_code != 200:
await message.edit_text("Something went wrong")
return
result = response.json()
averageScore = result["averageScore"]
try:
coverImage_url = result["imageUrl"]
coverImage = requests.get(url=coverImage_url).content
async with aiofiles.open("coverImage.jpg", mode="wb") as f:
await f.write(coverImage)
except Exception:
coverImage = None
title = result["title"]["english"]
trailer = result["trailer"]["id"]
description = result["description"]
chapters = result["chapters"]
genres = ", ".join(result["genres"])
isAdult = result["isAdult"]
status = result["status"]
studios = ", ".join(result["studios"])
await message.delete()
await client.send_media_group(
chat_id,
[
InputMediaPhoto(
"coverImage.jpg",
caption=f"<b>Title:</b> <code>{title}</code>\n<b>Average Score:</b> <code>{averageScore}</code>\n<b>Status:</b> <code>{status}</code>\n<b>Genres:</b> <code>{genres}</code>\n<b>Chapters:</b> <code>{chapters}</code>\n<b>Is Adult:</b> <code>{isAdult}</code>\n<b>Studios:</b> <code>{studios}</code>\n<b>Description:</b> <code>{description}</code>\n<b>Trailer:</b> <a href='https://youtu.be/{trailer}'>Click Here</a>",
)
],
)
except MediaCaptionTooLong:
description = description[:850]
await message.delete()
await client.send_media_group(
chat_id,
[
InputMediaPhoto(
"coverImage.jpg",
caption=f"<b>Title:</b> <code>{title}</code>\n<b>Average Score:</b> <code>{averageScore}</code>\n<b>Status:</b> <code>{status}</code>\n<b>Genres:</b> <code>{genres}</code>\n<b>Chapters:</b> <code>{chapters}</code>\n<b>Is Adult:</b> <code>{isAdult}</code>\n<b>Studios:</b> <code>{studios}</code>\n<b>Description:</b> <code>{description}</code>\n<b>Trailer:</b> <a href='https://youtu.be/{trailer}'>Click Here</a>",
)
],
)
except Exception as e:
await message.edit_text(format_exc(e))
finally:
if os.path.exists("coverImage.jpg"):
os.remove("coverImage.jpg")
@Client.on_message(filters.command("character", prefix) & filters.me)
async def character(client: Client, message: Message):
try:
chat_id = message.chat.id
await message.edit_text("Processing...")
if len(message.command) > 1:
query = message.text.split(maxsplit=1)[1]
else:
message.edit_text(
"What should i search? You didn't provided me with any value to search"
)
response = requests.get(
url=f"{url}/anime/character?query={query}", headers=headers, timeout=5
)
if response.status_code != 200:
await message.edit_text("Something went wrong")
return
result = response.json()
try:
coverImage_url = result["image"]["large"]
coverImage = requests.get(url=coverImage_url).content
async with aiofiles.open("coverImage.jpg", mode="wb") as f:
await f.write(coverImage)
except Exception:
coverImage = None
age = result["age"]
description = result["description"]
height = result["height"]
name = result["name"]["full"]
native_name = result["name"]["native"]
read_more = result["siteUrl"]
await message.delete()
await client.send_media_group(
chat_id,
[
InputMediaPhoto(
"coverImage.jpg",
caption=f"**Name:** `{name}`\n**Native Name:** `{native_name}`\n**Age:** `{age}`\n**Height:** {height}\n**Description:** `{description}`[read more...]({read_more})",
parse_mode=enums.ParseMode.MARKDOWN,
)
],
)
except MediaCaptionTooLong:
description = description[:850]
await message.delete()
await client.send_media_group(
chat_id,
[
InputMediaPhoto(
"coverImage.jpg",
caption=f"**Name:** `{name}`\n**Native Name:** `{native_name}`\n**Age:** `{age}`\n**Height:** {height}\n**Description:** `{description}`[read more...]({read_more})",
parse_mode=enums.ParseMode.MARKDOWN,
)
],
)
except Exception as e:
await message.edit_text(format_exc(e))
finally:
if os.path.exists("coverImage.jpg"):
os.remove("coverImage.jpg")
modules_help["anilist"] = {
"anime_search": "Search for anime on Anilist",
"manga_search": "Search for manga on Anilist",
"character": "Search for character on Anilist",
}
+69
View File
@@ -0,0 +1,69 @@
from pyrogram import Client, filters, enums
from pyrogram.types import Message
# noinspection PyUnresolvedReferences
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
from aiohttp import ClientSession
from io import BytesIO
session = ClientSession()
class Post:
def __init__(self, source: dict, session: ClientSession):
self._json = source
self.session = session
@property
async def image(self):
return (
self.file_url
if self.file_url
else (
self.large_file_url
if self.large_file_url
else (
self.source
if self.source and "pximg" not in self.source
else await self.pximg if self.source else None
)
)
)
@property
async def pximg(self):
async with self.session.get(self.source) as response:
return BytesIO(await response.read())
def __getattr__(self, item):
return self._json.get(item)
async def random():
async with session.get(
url="https://danbooru.donmai.us/posts/random.json"
) as response:
return Post(await response.json(encoding="utf-8"), session)
@Client.on_message(filters.command(["arnd", "arandom"], prefix) & filters.me)
async def anime_handler(client: Client, message: Message):
try:
await message.edit("<b>Searching art</b>", parse_mode=enums.ParseMode.HTML)
ra = await random()
img = await ra.image
await message.reply_photo(
photo=img,
caption=f'<b>{ra.tag_string_general if ra.tag_string_general else "Untitled"}</b>',
parse_mode=enums.ParseMode.HTML,
)
return await message.delete()
except Exception as e:
await message.edit(format_exc(e), parse_mode=enums.ParseMode.HTML)
modules_help["anime"] = {
"arnd": "Random anime art (May get caught 18+)",
"arandom": "Random anime art (May get caught 18+)",
}
+72
View File
@@ -0,0 +1,72 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import asyncio
import requests
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
def get_neko_media(query):
return requests.get(f"https://nekos.life/api/v2/img/{query}").json()["url"]
@Client.on_message(filters.command("neko", prefix) & filters.me)
async def neko(_, message: Message):
if len(message.command) == 1:
await message.edit(
"<b>Neko type isn't provided\n"
f"You can get available neko types with <code>{prefix}neko_types</code></b>"
)
query = message.command[1]
await message.edit("<b>Loading...</b>")
try:
await message.edit(f"{get_neko_media(query)}", disable_web_page_preview=False)
except Exception as e:
await message.edit(format_exc(e))
@Client.on_message(filters.command(["nekotypes", "neko_types"], prefix) & filters.me)
async def neko_types_func(_, message: Message):
neko_types = """hug kiss tickle lewd neko pat lizard 8ball cat chat fact smug woof gasm goose cuddle avatar slap gecg feed fox_girl meow wallpaper spank waifu ngif name owoify spoiler why"""
await message.edit(" ".join(f"<code>{n}</code>" for n in neko_types.split()))
@Client.on_message(filters.command(["nekospam", "neko_spam"], prefix) & filters.me)
async def neko_spam(client: Client, message: Message):
query = message.command[1]
amount = int(message.command[2])
await message.delete()
for _ in range(amount):
if message.reply_to_message:
await message.reply_to_message.reply(get_neko_media(query))
else:
await client.send_message(message.chat.id, get_neko_media(query))
await asyncio.sleep(0.1)
modules_help["neko"] = {
"neko [type]*": "Get neko media",
"neko_types": "Available neko types",
"neko_spam [type]* [amount]*": "Start spam with neko media",
}
+43
View File
@@ -0,0 +1,43 @@
from random import choice, randint
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
@Client.on_message(filters.command(["aniq", "aq"], prefix) & filters.me)
async def aniquotes_handler(client: Client, message: Message):
if message.reply_to_message and message.reply_to_message.text:
query = message.reply_to_message.text[:512]
elif message.reply_to_message and message.reply_to_message.caption:
query = message.reply_to_message.caption[:512]
elif len(message.command) > 1:
query = message.text.split(maxsplit=1)[1][:512]
else:
return await message.edit(
"<b>[💮 Aniquotes] <i>Please enter text to create sticker.</i></b>",
parse_mode=enums.ParseMode.HTML,
)
try:
await message.delete()
result = await client.get_inline_bot_results("@quotafbot", query)
return await message.reply_inline_bot_result(
query_id=result.query_id,
result_id=result.results[randint(1, 2)].id,
reply_to_message_id=(
message.reply_to_message.id if message.reply_to_message else None
),
)
except Exception as e:
return await message.reply(
f"<b>[💮 Aniquotes]</b>\n<code>{format_exc(e)}</code>",
parse_mode=enums.ParseMode.HTML,
)
modules_help["aniquotes"] = {
"aq [text]": "Create animated sticker with text",
}
+256
View File
@@ -0,0 +1,256 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import os
from pyrogram import Client, filters
from pyrogram.raw import functions
from pyrogram.types import Message
from utils.config import pm_limit
from utils.db import db
from utils.misc import modules_help, prefix
anti_pm_enabled = filters.create(
lambda _, __, ___: db.get("core.antipm", "status", False)
)
in_contact_list = filters.create(lambda _, __, message: message.from_user.is_contact)
is_support = filters.create(lambda _, __, message: message.chat.is_support)
USER_WARNINGS = {}
@Client.on_message(
filters.private
& ~filters.me
& ~filters.bot
& ~in_contact_list
& ~is_support
& anti_pm_enabled
)
async def anti_pm_handler(client: Client, message: Message):
user_id = message.from_user.id
ids = message.chat.id
b_f = await client.get_me()
u_n = b_f.first_name
user = await client.get_users(ids)
u_f = user.first_name
default_text = db.get("core.antipm", "antipm_msg", None)
if default_text is None:
default_text = f"""<b>Hello, {u_f}!
This is the Assistant Of {u_n}.</b>
<i>My Boss is away or busy as of now, You can wait for him to respond.
Do not spam further messages else I may have to block you!</i>
<b>This is an automated message by the assistant.</b>
<b><u>Currently You Have <code>{USER_WARNINGS.get(user_id, 0)}</code> Warnings.</u></b>
"""
else:
default_text = default_text.format(
user=u_f, my_name=u_n, warns=USER_WARNINGS.get(user_id, 0)
)
if db.get("core.antipm", "spamrep", False):
user_info = await client.resolve_peer(ids)
await client.invoke(functions.messages.ReportSpam(peer=user_info))
if db.get("core.antipm", "block", False):
await client.block_user(user_id)
if db.get("core.antipm", f"disallowusers{ids}") == user_id != db.get(
"core.antipm", f"allowusers{ids}"
) or db.get("core.antipm", f"disallowusers{ids}") != user_id != db.get(
"core.antipm", f"allowusers{ids}"
):
default_pic = db.get("core.antipm", "antipm_pic", None)
if default_pic and os.path.exists(default_pic):
await client.send_photo(message.chat.id, default_pic, caption=default_text)
else:
await client.send_message(message.chat.id, default_text)
if user_id in USER_WARNINGS:
USER_WARNINGS[user_id] += 1
else:
USER_WARNINGS[user_id] = 1
if USER_WARNINGS[user_id] > pm_limit:
await client.send_message(
message.chat.id,
"<b>Ehm...! That was your Last warn, Bye Bye see you L0L</b>",
)
await client.block_user(user_id)
del USER_WARNINGS[user_id]
@Client.on_message(filters.command(["antipm", "anti_pm"], prefix) & filters.me)
async def anti_pm(_, message: Message):
if len(message.command) == 1:
if db.get("core.antipm", "status", False):
await message.edit(
"<b>Anti-PM status: enabled\n"
f"Disable with: </b><code>{prefix}antipm disable</code>"
)
else:
await message.edit(
"<b>Anti-PM status: disabled\n"
f"Enable with: </b><code>{prefix}antipm enable</code>"
)
elif message.command[1] in ["enable", "on", "1", "yes", "true"]:
db.set("core.antipm", "status", True)
await message.edit("<b>Anti-PM enabled!</b>")
elif message.command[1] in ["disable", "off", "0", "no", "false"]:
db.set("core.antipm", "status", False)
await message.edit("<b>Anti-PM disabled!</b>")
else:
await message.edit(f"<b>Usage: {prefix}antipm [enable|disable]</b>")
@Client.on_message(filters.command(["antipm_report"], prefix) & filters.me)
async def antipm_report(_, message: Message):
if len(message.command) == 1:
if db.get("core.antipm", "spamrep", False):
await message.edit(
"<b>Spam-reporting enabled.\n"
f"Disable with: </b><code>{prefix}antipm_report disable</code>"
)
else:
await message.edit(
"<b>Spam-reporting disabled.\n"
f"Enable with: </b><code>{prefix}antipm_report enable</code>"
)
elif message.command[1] in ["enable", "on", "1", "yes", "true"]:
db.set("core.antipm", "spamrep", True)
await message.edit("<b>Spam-reporting enabled!</b>")
elif message.command[1] in ["disable", "off", "0", "no", "false"]:
db.set("core.antipm", "spamrep", False)
await message.edit("<b>Spam-reporting disabled!</b>")
else:
await message.edit(f"<b>Usage: {prefix}antipm_report [enable|disable]</b>")
@Client.on_message(filters.command(["antipm_block"], prefix) & filters.me)
async def antipm_block(_, message: Message):
if len(message.command) == 1:
if db.get("core.antipm", "block", False):
await message.edit(
"<b>Blocking users enabled.\n"
f"Disable with: </b><code>{prefix}antipm_block disable</code>"
)
else:
await message.edit(
"<b>Blocking users disabled.\n"
f"Enable with: </b><code>{prefix}antipm_block enable</code>"
)
elif message.command[1] in ["enable", "on", "1", "yes", "true"]:
db.set("core.antipm", "block", True)
await message.edit("<b>Blocking users enabled!</b>")
elif message.command[1] in ["disable", "off", "0", "no", "false"]:
db.set("core.antipm", "block", False)
await message.edit("<b>Blocking users disabled!</b>")
else:
await message.edit(f"<b>Usage: {prefix}antipm_block [enable|disable]</b>")
@Client.on_message(filters.command(["a"], prefix) & filters.me)
async def add_contact(_, message: Message):
ids = message.chat.id
db.set("core.antipm", f"allowusers{ids}", ids)
if ids in USER_WARNINGS:
del USER_WARNINGS[ids]
await message.edit("User Approved!")
@Client.on_message(filters.command(["d"], prefix) & filters.me)
async def del_contact(_, message: Message):
ids = message.chat.id
db.set("core.antipm", f"disallowusers{ids}", ids)
db.remove("core.antipm", f"allowusers{ids}")
await message.edit("User DisApproved!")
@Client.on_message(filters.command(["setantipmmsg", "sam"], prefix) & filters.me)
async def set_antipm_msg(_, message: Message):
if not message.reply_to_message:
db.set("core.antipm", "antipm_msg", None)
await message.edit("antipm message set to default.")
return
msg = message.reply_to_message
afk_msg = msg.text or msg.caption
if not afk_msg:
return await message.edit(
"Reply to a text or caption message to set it as your antipm message."
)
if len(afk_msg) > 200:
return await message.edit(
"antipm message is too long. It should be less than 200 characters."
)
if "{user}" not in afk_msg:
return await message.edit(
"antipm message must contain <code>{user}</code> to mention the user."
)
if "{my_name}" not in afk_msg:
return await message.edit(
"antipm message must contain <code>{my_name}</code> to mention your name."
)
if "{warns}" not in afk_msg:
return await message.edit(
"antipm message must contain <code>{warns}</code> to mention the warns count."
)
old_afk_msg = db.get("core.antipm", "antipm_msg", None)
if old_afk_msg:
db.remove("core.antipm", "antipm_msg")
db.set("core.antipm", "antipm_msg", afk_msg)
await message.edit(f"antipm message set to:\n\n{afk_msg}")
@Client.on_message(filters.command(["setantipmpic", "sap"], prefix) & filters.me)
async def set_antipm_pic(_, message: Message):
if not message.reply_to_message or not message.reply_to_message.photo:
db.set("core.antipm", "antipm_pic", None)
await message.edit("antipm picture set to default.")
return
await message.edit("Setting antipm picture...")
photo = await message.reply_to_message.download("antipm_pic.jpg")
old_antipm_pic = db.get("core.antipm", "antipm_pic", None)
if old_antipm_pic:
db.remove("core.antipm", "antipm_pic")
db.set("core.antipm", "antipm_pic", photo)
await message.edit("antipm picture set successfully.")
modules_help["antipm"] = {
"antipm [enable|disable]*": "Enable Pm permit",
"antipm_report [enable|disable]*": "Enable spam reporting",
"antipm_block [enable|disable]*": "Enable user blocking",
"setantipmmsg [reply to message]*": "Set antipm message. Use {user} to mention the user and {my_name} to mention your name and {warns} to mention the warns count.",
"sam [reply to message]*": "Set antipm message. Use {user} to mention the user and {my_name} to mention your name and {warns} to mention the warns count.",
"setantipmpic [reply to photo]*": "Set antipm picture.",
"sap [reply to photo]*": "Set antipm picture.",
"a": "Approve User",
"d": "DisApprove User",
}
+134
View File
@@ -0,0 +1,134 @@
import uuid
import re
from aiohttp import ClientSession, FormData
from pyrogram import Client, filters
from utils.misc import modules_help, prefix
def id_generator() -> str:
return str(uuid.uuid4())
@Client.on_message(filters.command(["bbox", "blackbox"], prefix) & filters.me)
async def blackbox(client, message):
m = message
msg = await m.edit_text("🔍")
if len(m.text.split()) == 1:
return await msg.edit_text(
"Type some query buddy 🐼\n"
f"{prefix}blackbox text with reply to the photo or just text"
)
else:
try:
session = ClientSession()
prompt = m.text.split(maxsplit=1)[1]
user_id = id_generator()
image = None
if m.reply_to_message and (
m.reply_to_message.photo
or (
m.reply_to_message.sticker
and not m.reply_to_message.sticker.is_video
)
):
file_name = f"blackbox_{m.chat.id}.jpeg"
file_path = await m.reply_to_message.download(file_name=file_name)
with open(file_path, "rb") as file:
image = file.read()
if image:
data = FormData()
data.add_field("fileName", file_name)
data.add_field("userId", user_id)
data.add_field(
"image", image, filename=file_name, content_type="image/jpeg"
)
api_url = "https://www.blackbox.ai/api/upload"
try:
async with session.post(api_url, data=data) as response:
response_json = await response.json()
except Exception as e:
return await msg.edit(f"❌ Error: {str(e)}")
messages = [
{
"role": "user",
"content": response_json["response"] + "\n#\n" + prompt,
}
]
data = {
"messages": messages,
"user_id": user_id,
"codeModelMode": True,
"agentMode": {},
"trendingAgentMode": {},
}
headers = {"Content-Type": "application/json"}
url = "https://www.blackbox.ai/api/chat"
try:
async with session.post(
url, headers=headers, json=data
) as response:
response_text = await response.text()
except Exception as e:
return await msg.edit(f"❌ Error: {str(e)}")
cleaned_response_text = re.sub(
r"^\$?@?\$?v=undefined-rv\d+@?\$?|\$?@?\$?v=v\d+\.\d+-rv\d+@?\$?",
"",
response_text,
)
text = cleaned_response_text.strip()[2:]
if "$~~~$" in text:
text = re.sub(r"\$~~~\$.*?\$~~~\$", "", text, flags=re.DOTALL)
rdata = {"reply": text}
return await msg.edit_text(text=rdata["reply"])
else:
reply = m.reply_to_message
if reply and reply.text:
prompt = f"Old conversation:\n{reply.text}\n\nQuestion:\n{prompt}"
messages = [{"role": "user", "content": prompt}]
data = {
"messages": messages,
"user_id": user_id,
"codeModelMode": True,
"agentMode": {},
"trendingAgentMode": {},
}
headers = {"Content-Type": "application/json"}
url = "https://www.blackbox.ai/api/chat"
try:
async with session.post(
url, headers=headers, json=data
) as response:
response_text = await response.text()
except Exception as e:
return await msg.edit(f"❌ Error: {str(e)}")
cleaned_response_text = re.sub(
r"^\$?@?\$?v=undefined-rv\d+@?\$?|\$?@?\$?v=v\d+\.\d+-rv\d+@?\$?",
"",
response_text,
)
text = cleaned_response_text.strip()[2:]
if "$~~~$" in text:
text = re.sub(r"\$~~~\$.*?\$~~~\$", "", text, flags=re.DOTALL)
rdata = {"reply": text}
return await msg.edit_text(text=rdata["reply"])
except Exception as e:
return await msg.edit(f" Error: {str(e)}")
finally:
await session.close()
modules_help["blackbox"] = {
"blackbox [query]*": "Ask anything to Blackbox",
"bbox [query]*": "Ask anything to Blackbox",
}
+46
View File
@@ -0,0 +1,46 @@
import asyncio
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
@Client.on_message(filters.command("calc", prefix) & filters.me)
async def calc(_, message: Message):
if len(message.command) <= 1:
return
args = " ".join(message.command[1:])
try:
result = str(eval(args))
if len(result) > 4096:
i = 0
for x in range(0, len(result), 4096):
if i == 0:
await message.edit(
f"<i>{args}</i><b>=</b><code>{result[x:x + 4000]}</code>",
parse_mode="HTML",
)
else:
await message.reply(
f"<code>{result[x:x + 4096]}</code>", parse_mode="HTML"
)
i += 1
await asyncio.sleep(0.18)
else:
await message.edit(
f"<i>{args}</i><b>=</b><code>{result}</code>", parse_mode="HTML"
)
except Exception as e:
await message.edit(f"<i>{args}=</i><b>=</b><code>{e}</code>", parse_mode="HTML")
modules_help["calculator"] = {
"calc [expression]*": "solve a math problem\n"
"+ addition\n"
" subtraction\n"
"* multiplication\n"
"/ division\n"
"** degree"
}
+57
View File
@@ -0,0 +1,57 @@
import base64, os
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_exc, import_library
clarifai = import_library("clarifai")
from clarifai.client.model import Model
@Client.on_message(filters.command("cdxl", prefix) & filters.me)
async def cdxl(c: Client, message: Message):
try:
chat_id = message.chat.id
await message.edit_text("<code>Please Wait...</code>")
if len(message.command) > 1:
prompt = message.text.split(maxsplit=1)[1]
elif message.reply_to_message:
prompt = message.reply_to_message.text
else:
await message.edit_text(
f"<b>Usage: </b><code>{prefix}vdxl [prompt/reply to prompt]</code>"
)
return
inference_params = dict(width=1024, height=1024, steps=50, cfg_scale=9.0)
model_prediction = Model(
"https://clarifai.com/stability-ai/stable-diffusion-2/models/stable-diffusion-xl"
).predict_by_bytes(
prompt.encode(), input_type="text", inference_params=inference_params
)
output_base64 = model_prediction.outputs[0].data.image.base64
with open("sdxl_out.png", "wb") as f:
f.write(output_base64)
await message.delete()
await c.send_photo(
chat_id,
photo=f"sdxl_out.png",
caption=f"<b>Prompt:</b><code>{prompt}</code>",
)
os.remove(f"sdxl_out.png")
except Exception as e:
await message.edit_text(f"An error occurred: {format_exc(e)}")
modules_help["cdxl"] = {
"cdxl [prompt/reply to prompt]*": "Text to Image with SDXL model",
}
+105
View File
@@ -0,0 +1,105 @@
from pyrogram import Client, enums, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.config import cohere_key
from utils.db import db
from utils.scripts import format_exc, import_library, restart
cohere = import_library("cohere")
co = cohere.Client(cohere_key)
chatai_users = db.getaiusers()
@Client.on_message(filters.command("addai", prefix) & filters.me)
async def adduser(_, message: Message):
if len(message.command) > 1:
user_id = message.text.split(maxsplit=1)[1]
if user_id.isdigit():
user_id = int(user_id)
db.addaiuser(user_id)
await message.edit_text("<b>User ID Added</b>")
restart()
else:
await message.edit_text("<b>User ID is invalid.</b>")
return
else:
await message.edit_text(f"<b>Usage: </b><code>{prefix}addai [user_id]</code>")
return
@Client.on_message(filters.command("remai", prefix) & filters.me)
async def remuser(_, message: Message):
if len(message.command) > 1:
user_id = message.text.split(maxsplit=1)[1]
if user_id.isdigit():
user_id = int(user_id)
db.remaiuser(user_id)
await message.edit_text("<b>User ID Removed</b>")
restart()
else:
await message.edit_text("<b>User ID is invalid.</b>")
return
else:
await message.edit_text(f"<b>Usage: </b><code>{prefix}remai [user_id]</code>")
return
@Client.on_message(filters.user(users=chatai_users) & filters.text)
async def chatbot(_, message: Message):
user_id = message.chat.id
if user_id in chatai_users:
pass
else:
return
try:
await message.reply_chat_action(enums.ChatAction.TYPING)
chat_history = db.get_chat_history(user_id)
prompt = message.text
db.add_chat_history(user_id, {"role": "USER", "message": prompt})
response = co.chat(
chat_history=chat_history,
model="command-r-plus",
message=prompt,
temperature=0.3,
connectors=[{"id": "web-search", "options": {"site": "wikipedia.com"}}],
prompt_truncation="AUTO",
)
db.add_chat_history(user_id, {"role": "CHATBOT", "message": response.text})
await message.reply_text(
f"{response.text}", parse_mode=enums.ParseMode.MARKDOWN
)
except Exception as e:
await message.reply_text(f"An error occurred: {format_exc(e)}")
@Client.on_message(filters.command("chatoff", prefix) & filters.me)
async def chatoff(_, message: Message):
db.remove("core.chatbot", "chatai_users")
await message.reply_text("<b>ChatBot is off now</b>")
restart()
@Client.on_message(filters.command("listai", prefix) & filters.me)
async def listai(_, message: Message):
await message.edit_text(
f"<b>User ID's Currently in AI ChatBot List:</b>\n <code>{chatai_users}</code>"
)
modules_help["chatbot"] = {
"addai [user_id]*": "Add A user to AI ChatBot List",
"remai [user_id]*": "Remove A user from AI ChatBot List",
"listai": "List A user from AI ChatBot List",
"chatoff": "Turn off AI ChatBot",
}
+146
View File
@@ -0,0 +1,146 @@
import asyncio
import os
from io import BytesIO
from PIL import Image, ImageDraw, ImageFilter, ImageOps
from pyrogram import Client, filters, enums
from pyrogram.types import Message
# noinspection PyUnresolvedReferences
from utils.misc import modules_help, prefix
# noinspection PyUnresolvedReferences
from utils.scripts import import_library, format_exc
VideoFileClip = import_library("moviepy", "moviepy==2.2.1").VideoFileClip
im = None
def process_img(filename):
global im
im = Image.open(f"downloads/{filename}")
w, h = im.size
img = Image.new("RGBA", (w, h), (0, 0, 0, 0))
img.paste(im, (0, 0))
m = min(w, h)
img = img.crop(((w - m) // 2, (h - m) // 2, (w + m) // 2, (h + m) // 2))
w, h = img.size
mask = Image.new("L", (w, h), 0)
draw = ImageDraw.Draw(mask)
draw.ellipse((10, 10, w - 10, h - 10), fill=255)
mask = mask.filter(ImageFilter.GaussianBlur(2))
img = ImageOps.fit(img, (w, h))
img.putalpha(mask)
im = BytesIO()
im.name = "img.webp"
img.save(im)
im.seek(0)
video = None
def process_vid(filename):
global video
video = VideoFileClip(f"downloads/{filename}")
w, h = video.size
m = min(w, h)
box = {
"x1": (w - m) // 2,
"y1": (h - m) // 2,
"x2": (w + m) // 2,
"y2": (h + m) // 2,
}
video = video.cropped(**box)
@Client.on_message(filters.command(["circle", "round"], prefix) & filters.me)
async def circle(_, message: Message):
try:
if not message.reply_to_message:
return await message.reply(
"<b>Reply is required for this command</b>",
parse_mode=enums.ParseMode.HTML,
)
if message.reply_to_message.photo:
filename = "circle.jpg"
typ = "photo"
elif message.reply_to_message.sticker:
if message.reply_to_message.sticker.is_video:
return await message.reply(
"<b>Video stickers is not supported</b>",
parse_mode=enums.ParseMode.HTML,
)
filename = "circle.webp"
typ = "photo"
elif message.reply_to_message.video:
filename = "circle.mp4"
typ = "video"
elif message.reply_to_message.document:
_filename = message.reply_to_message.document.file_name.casefold()
if _filename.endswith(".png"):
filename = "circle.png"
typ = "photo"
elif _filename.endswith(".jpg"):
filename = "circle.jpg"
typ = "photo"
elif _filename.endswith(".jpeg"):
filename = "circle.jpeg"
typ = "photo"
elif _filename.endswith(".webp"):
filename = "circle.webp"
typ = "photo"
elif _filename.endswith(".mp4"):
filename = "circle.mp4"
typ = "video"
else:
return await message.reply(
"<b>Invalid file type</b>", parse_mode=enums.ParseMode.HTML
)
else:
return await message.reply(
"<b>Invalid file type</b>", parse_mode=enums.ParseMode.HTML
)
if typ == "photo":
await message.edit(
"<b>Processing image</b>📷", parse_mode=enums.ParseMode.HTML
)
await message.reply_to_message.download(f"downloads/{filename}")
await asyncio.get_event_loop().run_in_executor(None, process_img, filename)
await message.delete()
return await message.reply_sticker(
sticker=im, reply_to_message_id=message.reply_to_message.id
)
else:
await message.edit(
"<b>Processing video</b>🎥", parse_mode=enums.ParseMode.HTML
)
await message.reply_to_message.download(f"downloads/{filename}")
await asyncio.get_event_loop().run_in_executor(None, process_vid, filename)
await message.edit("<b>Saving video</b>📼", parse_mode=enums.ParseMode.HTML)
await asyncio.get_event_loop().run_in_executor(
None, video.write_videofile, "downloads/result.mp4"
)
await message.delete()
await message.reply_video_note(
video_note="downloads/result.mp4",
duration=int(video.duration),
reply_to_message_id=message.reply_to_message.id,
)
if isinstance(video, VideoFileClip):
video.close()
os.remove(f"downloads/{filename}")
os.remove("downloads/result.mp4")
except Exception as e:
await message.reply(format_exc(e), parse_mode=enums.ParseMode.HTML)
modules_help["circle"] = {
"round": "Round a photo or video.",
"circle": "Circle a photo or video.",
}
+79
View File
@@ -0,0 +1,79 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.raw import functions
from pyrogram.types import Message
from utils.misc import modules_help, prefix
@Client.on_message(filters.command(["clear_@"], prefix) & filters.me)
async def solo_mention_clear(client: Client, message: Message):
await message.delete()
peer = await client.resolve_peer(message.chat.id)
request = functions.messages.ReadMentions(peer=peer)
await client.invoke(request)
@Client.on_message(filters.command(["clear_all_@"], prefix) & filters.me)
async def global_mention_clear(client: Client, message: Message):
counter: int = 0
await message.edit_text(
f"<b>Clearing all mentions...</b>\n\n<b>Cleared:</b> <code>{counter}</code> chats"
)
async for dialog in client.get_dialogs():
peer = await client.resolve_peer(dialog.chat.id)
request = functions.messages.ReadMentions(peer=peer)
await client.invoke(request)
counter += 1
await message.edit_text(
f"<b>Clearing all mentions...</b>\n\n<b>Cleared:</b> <code>{counter}</code> chats"
)
await message.delete()
@Client.on_message(filters.command(["clear_reacts"], prefix) & filters.me)
async def solo_reaction_clear(client: Client, message: Message):
await message.delete()
peer = await client.resolve_peer(message.chat.id)
request = functions.messages.ReadReactions(peer=peer)
await client.invoke(request)
@Client.on_message(filters.command(["clear_all_reacts"], prefix) & filters.me)
async def global_reaction_clear(client: Client, message: Message):
counter: int = 0
await message.edit_text(
f"<b>Clearing all reactions...</b>\n\n<b>Cleared:</b> <code>{counter}</code> chats"
)
async for dialog in client.get_dialogs():
peer = await client.resolve_peer(dialog.chat.id)
request = functions.messages.ReadReactions(peer=peer)
await client.invoke(request)
counter += 1
await message.edit_text(
f"<b>Clearing all reactions...</b>\n\n<b>Cleared:</b> <code>{counter}</code> chats"
)
await message.delete()
modules_help["clear_notifs"] = {
"clear_@": "clear all mentions in this chat",
"clear_all_@": "clear all mentions in all chats",
"clear_reacts": "clear all reactions in this chat",
"clear_all_reacts": "clear all reactions in all chats (except private chats)",
}
+134
View File
@@ -0,0 +1,134 @@
import asyncio
from json import tool
from utils.scripts import import_library
from utils.config import cohere_key
cohere = import_library("cohere")
import cohere
co = cohere.Client(cohere_key)
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
from utils.db import db
from utils.rentry import paste as rentry_paste
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from pyrogram.errors import MessageTooLong
@Client.on_message(filters.command("cohere", prefix) & filters.me)
async def cohere(c: Client, message: Message):
try:
user_id = message.from_user.id
chat_history = db.get_chat_history(user_id)
if len(message.command) > 1:
prompt = message.text.split(maxsplit=1)[1]
elif message.reply_to_message:
prompt = message.reply_to_message.text
else:
await message.edit_text(
f"<b>Usage: </b><code>{prefix}cohere [prompt/reply to message]</code>"
)
return
db.add_chat_history(user_id, {"role": "USER", "message": prompt})
await message.edit_text("<code>Umm, lemme think...</code>")
response = co.chat_stream(
chat_history=chat_history,
model="command-r-plus",
message=prompt,
temperature=0.8,
tools=[{"name": "internet_search"}],
connectors=[],
prompt_truncation="OFF",
)
output = ""
tool_message = ""
data = []
for event in response:
if event.event_type == "tool-calls-chunk":
if event.tool_call_delta and event.tool_call_delta.text is None:
tool_message += ""
else:
tool_message += event.text
if event.event_type == "search-results":
data.append(event.documents)
if event.event_type == "text-generation":
output += event.text
if output == "":
output = "I can't seem to find an answer to that"
db.add_chat_history(user_id, {"role": "CHATBOT", "message": output})
await message.edit_text(f"<code>{tool_message}</code>")
await asyncio.sleep(5)
try:
data = data[0]
references = ""
reference_dict = {}
for item in data:
title = item["title"]
url = item["url"]
if title not in reference_dict:
reference_dict[title] = url
i = 1
for title, url in reference_dict.items():
references += f"**{i}.** [{title}]({url})\n"
i += 1
await message.edit_text(
f"**Question:**`{prompt}`\n**Answer:** {output}\n\n**References:**\n{references}",
parse_mode=enums.ParseMode.MARKDOWN,
disable_web_page_preview=True,
)
except IndexError:
references = ""
await message.edit_text(
f"**Question:**`{prompt}`\n**Answer:** {output}\n",
parse_mode=enums.ParseMode.MARKDOWN,
disable_web_page_preview=True,
)
except MessageTooLong:
await message.edit_text(
"<code>Output is too long... Pasting to rentry...</code>"
)
try:
output = output + "\n\n" + references if references else output
rentry_url, edit_code = await rentry_paste(
text=output, return_edit=True
)
except RuntimeError:
await message.edit_text(
"<b>Error:</b> <code>Failed to paste to rentry</code>"
)
return
await c.send_message(
"me",
f"Here's your edit code for Url: {rentry_url}\nEdit code: <code>{edit_code}</code>",
disable_web_page_preview=True,
)
await message.edit_text(
f"<b>Output:</b> {rentry_url}\n<b>Note:</b> <code>Edit Code has been sent to your saved messages</code>",
disable_web_page_preview=True,
)
except Exception as e:
await message.edit_text(f"An error occurred: {format_exc(e)}")
modules_help["cohere"] = {
"cohere": "Chat with cohere ai"
+ "\nSupports Chat History\n"
+ "Supports real time internet search"
}
+93
View File
@@ -0,0 +1,93 @@
import random
from io import BytesIO
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import import_library
requests = import_library("requests")
PIL = import_library("PIL", "pillow")
from PIL import Image, ImageDraw, ImageFont
@Client.on_message(filters.command(["dem"], prefix) & filters.me)
async def demotivator(client: Client, message: Message):
await message.edit(
"<code>Process of demotivation...</code>", parse_mode=enums.ParseMode.HTML
)
font = requests.get(
"https://github.com/The-MoonTg-project/files/blob/main/Times%20New%20Roman.ttf?raw=true"
)
f = font.content
template_dem = requests.get(
"https://raw.githubusercontent.com/files/main/demotivator.png"
)
if message.reply_to_message:
words = ["random", "text", "typing", "fuck"]
if message.reply_to_message.photo:
donwloads = await client.download_media(
message.reply_to_message.photo.file_id
)
photo = Image.open(f"{donwloads}")
resize_photo = photo.resize((469, 312))
text = (
message.text.split(" ", maxsplit=1)[1]
if len(message.text.split()) > 1
else random.choice(words)
)
im = Image.open(BytesIO(template_dem.content))
im.paste(resize_photo, (65, 48))
text_font = ImageFont.truetype(BytesIO(f), 22)
text_draw = ImageDraw.Draw(im)
text_draw.multiline_text(
(299, 412), text, font=text_font, fill=(255, 255, 255), anchor="ms"
)
im.save(f"downloads/{message.id}.png")
await message.reply_to_message.reply_photo(f"downloads/{message.id}.png")
await message.delete()
elif message.reply_to_message.sticker:
if not message.reply_to_message.sticker.is_animated:
donwloads = await client.download_media(
message.reply_to_message.sticker.file_id
)
photo = Image.open(f"{donwloads}")
resize_photo = photo.resize((469, 312))
text = (
message.text.split(" ", maxsplit=1)[1]
if len(message.text.split()) > 1
else random.choice(words)
)
im = Image.open(BytesIO(template_dem.content))
im.paste(resize_photo, (65, 48))
text_font = ImageFont.truetype(BytesIO(f), 22)
text_draw = ImageDraw.Draw(im)
text_draw.multiline_text(
(299, 412), text, font=text_font, fill=(255, 255, 255), anchor="ms"
)
im.save(f"downloads/{message.id}.png")
await message.reply_to_message.reply_photo(
f"downloads/{message.id}.png"
)
await message.delete()
else:
await message.edit(
"<b>Animated stickers are not supported</b>",
parse_mode=enums.ParseMode.HTML,
)
else:
await message.edit(
"<b>Need to answer the photo/sticker</b>",
parse_mode=enums.ParseMode.HTML,
)
else:
await message.edit(
"<b>Need to answer the photo/sticker</b>", parse_mode=enums.ParseMode.HTML
)
modules_help["demotivator"] = {
"dem [text]*": "Reply to the picture to make a demotivator out of it"
}
+84
View File
@@ -0,0 +1,84 @@
import os
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import import_library
lottie = import_library("lottie")
from lottie.exporters import exporters
from lottie.importers import importers
@Client.on_message(filters.command("destroy", prefix) & filters.me)
async def destroy_sticker(client: Client, message: Message):
"""Destroy animated stickers by modifying their animation properties"""
try:
reply = message.reply_to_message
if not reply or not reply.sticker or not reply.sticker.is_animated:
return await message.edit(
"**Please reply to an animated sticker!**",
parse_mode=enums.ParseMode.MARKDOWN,
)
edit_msg = await message.edit(
"**🔄 Destroying sticker...**", parse_mode=enums.ParseMode.MARKDOWN
)
# Download sticker
tgs_path = await reply.download()
if not tgs_path or not os.path.exists(tgs_path):
return await edit_msg.edit(
"**❌ Download failed!**", parse_mode=enums.ParseMode.MARKDOWN
)
# Conversion process
json_path = "temp.json"
output_path = "MoonUB.tgs"
importer = importers.get_from_filename(tgs_path)
if not importer:
return await edit_msg.edit(
"**❌ JSON conversion failed!**", parse_mode=enums.ParseMode.MARKDOWN
)
animation = importer.process(tgs_path)
exporter = exporters.get_from_filename(json_path)
exporter.process(animation, json_path)
# Modify JSON data
with open(json_path, "r+") as f:
content = f.read()
modified = (
content.replace("[1]", "[2]")
.replace("[2]", "[3]")
.replace("[3]", "[4]")
.replace("[4]", "[5]")
.replace("[5]", "[6]")
)
f.seek(0)
f.write(modified)
f.truncate()
importer = importers.get_from_filename(json_path)
animation = importer.process(json_path)
exporter = exporters.get_from_filename(output_path)
exporter.process(animation, output_path)
# Send result
await message.reply_document(output_path, reply_to_message_id=reply.id)
await edit_msg.delete()
except Exception as e:
await message.edit(f"**❌ Error:** `{e}`", parse_mode=enums.ParseMode.MARKDOWN)
finally:
# Cleanup temporary files
for file_path in [tgs_path, json_path, output_path]:
if file_path and os.path.exists(file_path):
try:
os.remove(file_path)
except Exception as clean_error:
print(f"Cleanup error: {clean_error}")
modules_help["destroy"] = {"destroy [reply]": "Modify and destroy animated stickers"}
+33
View File
@@ -0,0 +1,33 @@
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
import asyncio
@Client.on_message(filters.command("dice", prefix) & filters.me)
async def dice_text(client: Client, message: Message):
try:
value = int(message.command[1])
if value not in range(1, 7):
raise AssertionError
except (ValueError, IndexError, AssertionError):
return await message.edit(
"<b>Invalid value</b>", parse_mode=enums.ParseMode.HTML
)
try:
message.dice = type("bruh", (), {"value": 0})()
while message.dice.value != value:
message = (
await asyncio.gather(
message.delete(), client.send_dice(message.chat.id)
)
)[1]
except Exception as e:
await message.edit(format_exc(e), parse_mode=enums.ParseMode.HTML)
modules_help["dice"] = {
"dice [1-6]*": "Generate dice with specified value. Works only in groups"
}
+313
View File
@@ -0,0 +1,313 @@
# Copyright (C) 2019 The Raphielscape Company LLC.
#
# Licensed under the Raphielscape Public License, Version 1.d (the "License");
# you may not use this file except in compliance with the License.
#
""" Userbot module containing various sites direct links generators"""
import json
import re
import urllib.parse
from random import choice
from subprocess import PIPE, Popen
import requests
from bs4 import BeautifulSoup
from humanize import naturalsize
from pyrogram import Client, enums, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
def subprocess_run(cmd):
reply = ""
cmd_args = cmd.split()
subproc = Popen(
cmd_args,
stdout=PIPE,
stderr=PIPE,
universal_newlines=True,
executable="bash",
)
talk = subproc.communicate()
exitCode = subproc.returncode
if exitCode != 0:
reply += (
"```An error was detected while running the subprocess:\n"
f"exit code: {exitCode}\n"
f"stdout: {talk[0]}\n"
f"stderr: {talk[1]}```"
)
return reply
return talk
@Client.on_message(filters.command("direct", prefix) & filters.me)
async def direct_link_generator(_, m: Message):
if len(m.command) > 1:
message = m.text.split(maxsplit=1)[1]
elif m.reply_to_message:
message = m.reply_to_message.text
else:
await m.edit(f"<b>Usage: </b><code>{prefix}direct [url]</code>")
return
reply = ""
links = re.findall(r"\bhttps?://.*\.\S+", message)
if not links:
reply = "`No links found!`"
await m.edit(reply, parse_mode=enums.ParseMode.MARKDOWN)
for link in links:
if "drive.google.com" in link:
reply += gdrive(link)
elif "yadi.sk" in link:
reply += yandex_disk(link)
elif "cloud.mail.ru" in link:
reply += cm_ru(link)
elif "mediafire.com" in link:
reply += mediafire(link)
elif "sourceforge.net" in link:
reply += sourceforge(link)
elif "osdn.net" in link:
reply += osdn(link)
elif "androidfilehost.com" in link:
reply += androidfilehost(link)
else:
reply += re.findall(r"\bhttps?://(.*?[^/]+)", link)[0] + " is not supported"
await m.edit(reply, parse_mode=enums.ParseMode.MARKDOWN)
def gdrive(url: str) -> str:
"""GDrive direct links generator"""
drive = "https://drive.google.com"
try:
link = re.findall(r"\bhttps?://drive\.google\.com\S+", url)[0]
except IndexError:
reply = "`No Google drive links found`\n"
return reply
file_id = ""
reply = ""
if link.find("view") != -1:
file_id = link.split("/")[-2]
elif link.find("open?id=") != -1:
file_id = link.split("open?id=")[1].strip()
elif link.find("uc?id=") != -1:
file_id = link.split("uc?id=")[1].strip()
url = f"{drive}/uc?export=download&id={file_id}"
download = requests.get(url, stream=True, allow_redirects=False)
cookies = download.cookies
try:
# In case of small file size, Google downloads directly
dl_url = download.headers["location"]
page = BeautifulSoup(download.content, "html.parser")
if "accounts.google.com" in dl_url: # non-public file
reply += "`Link is not public!`\n"
return reply
name = "Direct Download Link"
except KeyError:
# In case of download warning page
page = BeautifulSoup(download.content, "html.parser")
if download.headers is not None:
dl_url = download.headers.get("location")
page_element = page.find("a", {"id": "uc-download-link"})
if page_element is not None:
export = drive + page_element.get("href")
name = page.find("span", {"class": "uc-name-size"}).text
response = requests.get(
export, stream=True, allow_redirects=False, cookies=cookies
)
dl_url = response.headers["location"]
if "accounts.google.com" in dl_url:
name = page.find("span", {"class": "uc-name-size"}).text
reply += "Link is not public!"
return reply
if "=sharing" in dl_url:
name = page.find("span", {"class": "uc-name-size"}).text
reply += "```Provide GDrive Link not directc sharing of GDrive!```"
return reply
reply += f"[{name}]({dl_url})\n"
return reply
def yandex_disk(url: str) -> str:
"""Yandex.Disk direct links generator
Based on https://github.com/wldhx/yadisk-direct"""
reply = ""
try:
link = re.findall(r"\bhttps?://.*yadi\.sk\S+", url)[0]
except IndexError:
reply = "`No Yandex.Disk links found`\n"
return reply
api = "https://cloud-api.yandex.net/v1/disk/public/resources/download?public_key={}"
try:
dl_url = requests.get(api.format(link)).json()["href"]
name = dl_url.split("filename=")[1].split("&disposition")[0]
reply += f"[{name}]({dl_url})\n"
except KeyError:
reply += "`Error: File not found / Download limit reached`\n"
return reply
return reply
def cm_ru(url: str) -> str:
"""cloud.mail.ru direct links generator
Using https://github.com/JrMasterModelBuilder/cmrudl.py"""
reply = ""
try:
link = re.findall(r"\bhttps?://.*cloud\.mail\.ru\S+", url)[0]
except IndexError:
reply = "`No cloud.mail.ru links found`\n"
return reply
cmd = f"bin/cmrudl -s {link}"
result = subprocess_run(cmd)
try:
result = result[0].splitlines()[-1]
data = json.loads(result)
except json.decoder.JSONDecodeError:
reply += "`Error: Can't extract the link`\n"
return reply
except IndexError:
return reply
dl_url = data["download"]
name = data["file_name"]
size = naturalsize(int(data["file_size"]))
reply += f"[{name} ({size})]({dl_url})\n"
return reply
def mediafire(url: str) -> str:
"""MediaFire direct links generator"""
try:
link = re.findall(r"\bhttps?://.*mediafire\.com\S+", url)[0]
except IndexError:
reply = "`No MediaFire links found`\n"
return reply
reply = ""
page = BeautifulSoup(requests.get(link).content, "lxml")
info = page.find("a", {"aria-label": "Download file"})
dl_url = info.get("href")
size = re.findall(r"\(.*\)", info.text)[0]
name = page.find("div", {"class": "filename"}).text
reply += f"[{name} {size}]({dl_url})\n"
return reply
def sourceforge(url: str) -> str:
"""SourceForge direct links generator"""
try:
link = re.findall(r"\bhttps?://.*sourceforge\.net\S+", url)[0]
except IndexError:
reply = "`No SourceForge links found`\n"
return reply
file_path = re.findall(r"files(.*)/download", link)[0]
reply = f"Mirrors for __{file_path.split('/')[-1]}__\n"
project = re.findall(r"projects?/(.*?)/files", link)[0]
mirrors = (
f"https://sourceforge.net/settings/mirror_choices?"
f"projectname={project}&filename={file_path}"
)
page = BeautifulSoup(requests.get(mirrors).content, "html.parser")
info = page.find("ul", {"id": "mirrorList"}).findAll("li")
for mirror in info[1:]:
name = re.findall(r"\((.*)\)", mirror.text.strip())[0]
dl_url = (
f'https://{mirror["id"]}.dl.sourceforge.net/project/{project}/{file_path}'
)
reply += f"[{name}]({dl_url}) "
return reply
def osdn(url: str) -> str:
"""OSDN direct links generator"""
osdn_link = "https://osdn.net"
try:
link = re.findall(r"\bhttps?://.*osdn\.net\S+", url)[0]
except IndexError:
reply = "`No OSDN links found`\n"
return reply
page = BeautifulSoup(requests.get(link, allow_redirects=True).content, "lxml")
info = page.find("a", {"class": "mirror_link"})
link = urllib.parse.unquote(osdn_link + info["href"])
reply = f"Mirrors for __{link.split('/')[-1]}__\n"
mirrors = page.find("form", {"id": "mirror-select-form"}).findAll("tr")
for data in mirrors[1:]:
mirror = data.find("input")["value"]
name = re.findall(r"\((.*)\)", data.findAll("td")[-1].text.strip())[0]
dl_url = re.sub(r"m=(.*)&f", f"m={mirror}&f", link)
reply += f"[{name}]({dl_url}) "
return reply
def androidfilehost(url: str) -> str:
"""AFH direct links generator"""
try:
link = re.findall(r"\bhttps?://.*androidfilehost.*fid.*\S+", url)[0]
except IndexError:
reply = "`No AFH links found`\n"
return reply
fid = re.findall(r"\?fid=(.*)", link)[0]
session = requests.Session()
user_agent = useragent()
headers = {"user-agent": user_agent}
res = session.get(link, headers=headers, allow_redirects=True)
headers = {
"origin": "https://androidfilehost.com",
"accept-encoding": "gzip, deflate, br",
"accept-language": "en-US,en;q=0.9",
"user-agent": user_agent,
"content-type": "application/x-www-form-urlencoded; charset=UTF-8",
"x-mod-sbb-ctype": "xhr",
"accept": "*/*",
"referer": f"https://androidfilehost.com/?fid={fid}",
"authority": "androidfilehost.com",
"x-requested-with": "XMLHttpRequest",
}
data = {"submit": "submit", "action": "getdownloadmirrors", "fid": f"{fid}"}
mirrors = None
reply = ""
error = "`Error: Can't find Mirrors for the link`\n"
try:
req = session.post(
"https://androidfilehost.com/libs/otf/mirrors.otf.php",
headers=headers,
data=data,
cookies=res.cookies,
)
mirrors = req.json()["MIRRORS"]
except (json.decoder.JSONDecodeError, TypeError):
reply += error
if not mirrors:
reply += error
return reply
for item in mirrors:
name = item["name"]
dl_url = item["url"]
reply += f"[{name}]({dl_url}) "
return reply
def useragent():
"""
useragent random setter
"""
useragents = BeautifulSoup(
requests.get(
"https://developers.whatismybrowser.com/"
"useragents/explore/operating_system_name/android/"
).content,
"lxml",
).findAll("td", {"class": "useragent"})
if not useragents:
return "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"
user_agent = choice(useragents)
return user_agent.text
modules_help["direct"] = {
"direct": "Url/reply to Url\
\n\n<b>Syntax : </b><code>.direct [url/reply] </code>\
\n<b>Usage :</b> Generates direct download link from supported URL(s)\
\n\n<b>Supported websites : </b><code>Google Drive - MEGA.nz - Cloud Mail - Yandex.Disk - AFH - MediaFire - SourceForge - OSDN</code>"
}
+16
View File
@@ -0,0 +1,16 @@
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, requirements_list, prefix
@Client.on_message(filters.command("duck", prefix) & filters.me)
async def duckgo(client: Client, message: Message):
input_str = " ".join(message.command[1:])
sample_url = "https://duckduckgo.com/?q={}".format(input_str.replace(" ", "+"))
if sample_url:
link = sample_url.rstrip()
await message.edit_text(
"Let me 🦆 DuckDuckGo that for you:\n🔎 [{}]({})".format(input_str, link)
)
else:
await message.edit_text("something is wrong. please try again later.")
+17
View File
@@ -0,0 +1,17 @@
from random import randint
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from utils.misc import modules_help, prefix
@Client.on_message(filters.command("durov", prefix) & filters.me)
async def durov(_, message: Message):
await message.edit(
f"<b>Random post from channel: https://t.me/durov/{randint(21, 36500)}</b>",
parse_mode=enums.ParseMode.HTML,
)
modules_help["durov"] = {"durov": "Send random post from durov channel"}
+62
View File
@@ -0,0 +1,62 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, enums, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
# if your module has packages from PyPi
# from utils.scripts import import_library
# example_1 = import_library("example_1")
# example_2 = import_library("example_2")
# import_library() will automatically install required library
# if it isn't installed
@Client.on_message(filters.command("example_edit", prefix) & filters.me)
async def example_edit(client: Client, message: Message):
try:
await message.edit("<code>This is an example module</code>")
except Exception as e:
await message.edit(
f"<code>[{e.error_code}: {enums.MessageType.TEXT}] - {e.error_details}</code>"
)
@Client.on_message(filters.command("example_send", prefix) & filters.me)
async def example_send(client: Client, message: Message):
try:
await client.send_message(message.chat.id, "<b>This is an example module</b>")
except Exception as e:
await message.edit(
f"<code>[{e.error_code}: {enums.MessageType.TEXT}] - {e.error_details}</code>"
)
# This adds instructions for your module
modules_help["example"] = {
"example_send": "example send",
"example_edit": "example edit",
}
# modules_help["example"] = { "example_send [text]": "example send" }
# | | | |
# | | | └─ command description
# module_name command_name └─ optional command arguments
# (only snake_case) (only snake_case too)
+58
View File
@@ -0,0 +1,58 @@
import os
from random import randint
import aiohttp
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
async def download_sticker(url, filename):
headers = {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"accept-language": "en-US,en;q=0.9;q=0.8",
"cache-control": "no-cache",
"dnt": "1",
"pragma": "no-cache",
"priority": "u=0, i",
"sec-ch-ua": '"Not)A;Brand";v="8", "Chromium";v="138", "Microsoft Edge";v="138"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"',
"sec-fetch-dest": "document",
"sec-fetch-mode": "navigate",
"sec-fetch-site": "none",
"sec-fetch-user": "?1",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0",
}
cookies = {"country": "US", "lang": "en"}
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers, cookies=cookies) as response:
if response.status == 200:
with open(filename, "wb") as f:
f.write(await response.read())
@Client.on_message(filters.command(["f"], prefix) & filters.me)
async def random_stiker(client: Client, message: Message):
await message.delete()
random = randint(1, 63)
index = f"00{random}" if random < 10 else f"0{random}"
sticker = (
f"https://www.chpic.su/_data/stickers/f/FforRespect/FforRespect_{index}.webp"
)
await download_sticker(sticker, "f.webp")
if os.path.exists("f.webp"):
await client.send_document(
message.chat.id,
"f.webp",
reply_to_message_id=message.reply_to_message.id
if message.reply_to_message
else None,
)
os.remove("f.webp")
modules_help["f"] = {"f": "Send f to pay respect"}
+88
View File
@@ -0,0 +1,88 @@
from asyncio import sleep
from pyrogram import Client, filters, enums
from pyrogram.raw import functions
from pyrogram.types import Message, InputReplyToMessage
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
commands = {
"ftype": enums.ChatAction.TYPING,
"faudio": enums.ChatAction.UPLOAD_AUDIO,
"fvideo": enums.ChatAction.UPLOAD_VIDEO,
"fphoto": enums.ChatAction.UPLOAD_PHOTO,
"fdocument": enums.ChatAction.UPLOAD_DOCUMENT,
"flocation": enums.ChatAction.FIND_LOCATION,
"frvideo": enums.ChatAction.RECORD_VIDEO,
"frvoice": enums.ChatAction.RECORD_AUDIO,
"frvideor": enums.ChatAction.RECORD_VIDEO_NOTE,
"fvideor": enums.ChatAction.UPLOAD_VIDEO_NOTE,
"fgame": enums.ChatAction.PLAYING,
"fcontact": enums.ChatAction.CHOOSE_CONTACT,
"fstop": enums.ChatAction.CANCEL,
"fscrn": "screenshot",
}
# noinspection PyUnusedLocal
@Client.on_message(filters.command(list(commands), prefix) & filters.me)
async def fakeactions_handler(client: Client, message: Message):
cmd = message.command[0]
try:
sec = int(message.command[1])
if sec > 60:
sec = 60
except:
sec = None
await message.delete()
action = commands[cmd]
try:
if action != "screenshot":
if sec and action != enums.ChatAction.CANCEL:
while sec > 0:
await client.send_chat_action(
chat_id=message.chat.id, action=action
)
await sleep(1)
sec -= 1
return await client.send_chat_action(chat_id=message.chat.id, action=action)
else:
for _ in range(sec if sec else 1):
await client.invoke(
functions.messages.SendScreenshotNotification(
peer=await client.resolve_peer(message.chat.id),
reply_to=InputReplyToMessage(
reply_to_message_id=message.reply_to_message.id
),
random_id=client.rnd_id(),
)
)
await sleep(0.1)
except AttributeError:
return await client.send_message(
"me", f"Error in <b>fakeactions</b>" "reply to message is required"
)
except Exception as e:
return await client.send_message(
"me", f"Error in <b>fakeactions</b>" f" module:\n" + format_exc(e)
)
modules_help["fakeactions"] = {
"ftype [sec]": "Typing... action",
"faudio [sec]": "Sending voice... action",
"fvideo [sec]": "Sending video... action",
"fphoto [sec]": "Sending photo... action",
"fdocument [sec]": "Sending document... action",
"flocation [sec]": "Find location... action",
"fcontact [sec]": "Sending contact... action",
"frvideo [sec]": "Recording video... action",
"frvoice [sec]": "Recording voice... action",
"frvideor [sec]": "Recording round video... action",
"fvideor [sec]": "Uploading round video... action",
"fgame [sec]": "Playing game... action",
"fstop": "Stop actions",
"fscrn [amount] [reply_to_message]*": "Make screenshot action",
}
+264
View File
@@ -0,0 +1,264 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, ContinuePropagation, errors, filters
from pyrogram.types import (
InputMediaAudio,
InputMediaDocument,
InputMediaPhoto,
InputMediaVideo,
Message,
)
from utils.db import db
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
def get_filters_chat(chat_id):
return db.get("core.filters", f"{chat_id}", {})
def set_filters_chat(chat_id, filters_):
return db.set("core.filters", f"{chat_id}", filters_)
async def contains_filter(_, __, m):
return m.text and m.text.lower() in get_filters_chat(m.chat.id).keys()
contains = filters.create(contains_filter)
# noinspection PyTypeChecker
@Client.on_message(contains)
async def filters_main_handler(client: Client, message: Message):
value = get_filters_chat(message.chat.id)[message.text.lower()]
try:
await client.get_messages(int(value["CHAT_ID"]), int(value["MESSAGE_ID"]))
except errors.RPCError as exc:
raise ContinuePropagation from exc
if value.get("MEDIA_GROUP"):
messages_grouped = await client.get_media_group(
int(value["CHAT_ID"]), int(value["MESSAGE_ID"])
)
media_grouped_list = []
for _ in messages_grouped:
if _.photo:
if _.caption:
media_grouped_list.append(
InputMediaPhoto(_.photo.file_id, _.caption.HTML)
)
else:
media_grouped_list.append(InputMediaPhoto(_.photo.file_id))
elif _.video:
if _.caption:
if _.video.thumbs:
media_grouped_list.append(
InputMediaVideo(
_.video.file_id,
_.video.thumbs[0].file_id,
_.caption.HTML,
)
)
else:
media_grouped_list.append(
InputMediaVideo(_.video.file_id, _.caption.HTML)
)
elif _.video.thumbs:
media_grouped_list.append(
InputMediaVideo(_.video.file_id, _.video.thumbs[0].file_id)
)
else:
media_grouped_list.append(InputMediaVideo(_.video.file_id))
elif _.audio:
if _.caption:
media_grouped_list.append(
InputMediaAudio(_.audio.file_id, _.caption.HTML)
)
else:
media_grouped_list.append(InputMediaAudio(_.audio.file_id))
elif _.document:
if _.caption:
if _.document.thumbs:
media_grouped_list.append(
InputMediaDocument(
_.document.file_id,
_.document.thumbs[0].file_id,
_.caption.HTML,
)
)
else:
media_grouped_list.append(
InputMediaDocument(_.document.file_id, _.caption.HTML)
)
elif _.document.thumbs:
media_grouped_list.append(
InputMediaDocument(
_.document.file_id, _.document.thumbs[0].file_id
)
)
else:
media_grouped_list.append(InputMediaDocument(_.document.file_id))
await client.send_media_group(
message.chat.id, media_grouped_list, reply_to_message_id=message.id
)
else:
await client.copy_message(
message.chat.id,
int(value["CHAT_ID"]),
int(value["MESSAGE_ID"]),
reply_to_message_id=message.id,
)
raise ContinuePropagation
@Client.on_message(filters.command(["filter"], prefix) & filters.me)
async def filter_handler(client: Client, message: Message):
try:
if len(message.text.split()) < 2:
return await message.edit(
f"<b>Usage</b>: <code>{prefix}filter [name] (Reply required)</code>"
)
name = message.text.split(maxsplit=1)[1].lower()
chat_filters = get_filters_chat(message.chat.id)
if name in chat_filters.keys():
return await message.edit(
f"<b>Filter</b> <code>{name}</code> already exists."
)
if not message.reply_to_message:
return await message.edit("<b>Reply to message</b> please.")
try:
chat = await client.get_chat(db.get("core.notes", "chat_id", 0))
except (errors.RPCError, ValueError, KeyError):
# group is not accessible or isn't created
chat = await client.create_supergroup(
"Userbot_Notes_Filters", "Don't touch this group, please"
)
db.set("core.notes", "chat_id", chat.id)
chat_id = chat.id
if message.reply_to_message.media_group_id:
get_media_group = [
_.id
for _ in await client.get_media_group(
message.chat.id, message.reply_to_message.id
)
]
try:
message_id = await client.forward_messages(
chat_id, message.chat.id, get_media_group
)
except errors.ChatForwardsRestricted:
await message.edit(
"<b>Forwarding messages is restricted by chat admins</b>"
)
return
filter_ = {
"MESSAGE_ID": str(message_id[1].id),
"MEDIA_GROUP": True,
"CHAT_ID": str(chat_id),
}
else:
try:
message_id = await message.reply_to_message.forward(chat_id)
except errors.ChatForwardsRestricted:
message_id = await message.copy(chat_id)
filter_ = {
"MEDIA_GROUP": False,
"MESSAGE_ID": str(message_id.id),
"CHAT_ID": str(chat_id),
}
chat_filters.update({name: filter_})
set_filters_chat(message.chat.id, chat_filters)
return await message.edit(
f"<b>Filter</b> <code>{name}</code> has been added.",
)
except Exception as e:
return await message.edit(format_exc(e))
@Client.on_message(filters.command(["filters"], prefix) & filters.me)
async def filters_handler(_, message: Message):
try:
text = ""
for index, a in enumerate(get_filters_chat(message.chat.id).items(), start=1):
key, _ = a
key = key.replace("<", "").replace(">", "")
text += f"{index}. <code>{key}</code>\n"
text = f"<b>Your filters in current chat</b>:\n\n" f"{text}"
text = text[:4096]
return await message.edit(text)
except Exception as e:
return await message.edit(format_exc(e))
@Client.on_message(
filters.command(["delfilter", "filterdel", "fdel"], prefix) & filters.me
)
async def filter_del_handler(_, message: Message):
try:
if len(message.text.split()) < 2:
return await message.edit(
f"<b>Usage</b>: <code>{prefix}fdel [name]</code>",
)
name = message.text.split(maxsplit=1)[1].lower()
chat_filters = get_filters_chat(message.chat.id)
if name not in chat_filters.keys():
return await message.edit(
f"<b>Filter</b> <code>{name}</code> doesn't exists.",
)
del chat_filters[name]
set_filters_chat(message.chat.id, chat_filters)
return await message.edit(
f"<b>Filter</b> <code>{name}</code> has been deleted.",
)
except Exception as e:
return await message.edit(format_exc(e))
@Client.on_message(filters.command(["fsearch"], prefix) & filters.me)
async def filter_search_handler(_, message: Message):
try:
if len(message.text.split()) < 2:
return await message.edit(
f"<b>Usage</b>: <code>{prefix}fsearch [name]</code>",
)
name = message.text.split(maxsplit=1)[1].lower()
chat_filters = get_filters_chat(message.chat.id)
if name not in chat_filters.keys():
return await message.edit(
f"<b>Filter</b> <code>{name}</code> doesn't exists.",
)
return await message.edit(
f"<b>Trigger</b>:\n<code>{name}</code"
f">\n<b>Answer</b>:\n{chat_filters[name]}"
)
except Exception as e:
return await message.edit(format_exc(e))
modules_help["filters"] = {
"filter [name]": "Create filter (Reply required)",
"filters": "List of all triggers",
"fdel [name]": "Delete filter by name",
"fsearch [name]": "Info filter by name",
}
+106
View File
@@ -0,0 +1,106 @@
import asyncio
from pyrogram import Client, filters
from pyrogram.raw import functions
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
REPLACEMENT_MAP = {
"a": "ɐ",
"b": "q",
"c": "ɔ",
"d": "p",
"e": "ǝ",
"f": "ɟ",
"g": "ƃ",
"h": "ɥ",
"i": "",
"j": "ɾ",
"k": "ʞ",
"l": "l",
"m": "ɯ",
"n": "u",
"o": "o",
"p": "d",
"q": "b",
"r": "ɹ",
"s": "s",
"t": "ʇ",
"u": "n",
"v": "ʌ",
"w": "ʍ",
"x": "x",
"y": "ʎ",
"z": "z",
"A": "",
"B": "B",
"C": "Ɔ",
"D": "D",
"E": "Ǝ",
"F": "",
"G": "פ",
"H": "H",
"I": "I",
"J": "ſ",
"K": "K",
"L": "˥",
"M": "W",
"N": "N",
"O": "O",
"P": "Ԁ",
"Q": "Q",
"R": "R",
"S": "S",
"T": "",
"U": "",
"V": "Λ",
"W": "M",
"X": "X",
"Y": "",
"Z": "Z",
"0": "0",
"1": "Ɩ",
"2": "",
"3": "Ɛ",
"4": "",
"5": "ϛ",
"6": "9",
"7": "",
"8": "8",
"9": "6",
",": "'",
".": "˙",
"?": "¿",
"!": "¡",
'"': ",,",
"'": ",",
"(": ")",
")": "(",
"[": "]",
"]": "[",
"{": "}",
"}": "{",
"<": ">",
">": "<",
"&": "",
"_": "",
}
@Client.on_message(filters.command("flip", prefix) & filters.me)
async def flip(client: Client, message: Message):
text = " ".join(message.command[1:])
final_str = ""
for char in text:
if char in REPLACEMENT_MAP.keys():
new_char = REPLACEMENT_MAP[char]
else:
new_char = char
final_str += new_char
if text != final_str:
await message.edit(final_str)
else:
await message.edit(text)
modules_help["fliptext"] = {"flip [amount]*": "flip text upside down"}
+52
View File
@@ -0,0 +1,52 @@
import os
import io
import time
import requests
from pyrogram import filters, Client
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_exc, progress
def schellwithflux(args):
API_URL = "https://randydev-ryuzaki-api.hf.space/api/v1/akeno/fluxai"
payload = {"user_id": 1191668125, "args": args} # Please don't edit here
response = requests.post(API_URL, json=payload)
if response.status_code != 200:
print(f"Error status {response.status_code}")
return None
return response.content
@Client.on_message(filters.command("fluxai", prefix) & filters.me)
async def imgfluxai_(client: Client, message: Message):
question = message.text.split(" ", 1)[1] if len(message.command) > 1 else None
if not question:
return await message.reply_text("Please provide a question for Flux.")
try:
image_bytes = schellwithflux(question)
if image_bytes is None:
return await message.reply_text("Failed to generate an image.")
pro = await message.reply_text("Generating image, please wait...")
# Write the image bytes directly to a file
with open("flux_gen.jpg", "wb") as f:
f.write(image_bytes)
ok = await pro.edit_text("Uploading image...")
await message.reply_photo(
"flux_gen.jpg",
progress=progress,
progress_args=(ok, time.time(), "Uploading image..."),
)
await ok.delete()
if os.path.exists("flux_gen.jpg"):
os.remove("flux_gen.jpg")
except Exception as e:
await message.edit_text(format_exc(e))
modules_help["fluxai"] = {
"fluxai [prompt]*": "text to image fluxai",
}
+72
View File
@@ -0,0 +1,72 @@
# This scripts contains use cases for userbots
# This is used on my Moon-Userbot: https://github.com/The-MoonTg-project/Moon-Userbot
# YOu can check it out for uses example
import os
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from pyrogram.errors import MessageTooLong
from utils.misc import modules_help, prefix
from utils.scripts import format_exc, import_library
from utils.config import gemini_key
from utils.rentry import paste as rentry_paste
genai = import_library("google.generativeai", "google-generativeai")
genai.configure(api_key=gemini_key)
model = genai.GenerativeModel("gemini-2.0-flash")
@Client.on_message(filters.command("gemini", prefix) & filters.me)
async def say(client: Client, message: Message):
try:
await message.edit_text("<code>Please Wait...</code>")
if len(message.command) > 1:
prompt = message.text.split(maxsplit=1)[1]
elif message.reply_to_message:
prompt = message.reply_to_message.text
else:
await message.edit_text(
f"<b>Usage: </b><code>{prefix}gemini [prompt/reply to message]</code>"
)
return
chat = model.start_chat()
response = chat.send_message(prompt)
await message.edit_text(
f"**Question:**`{prompt}`\n**Answer:** {response.text}",
parse_mode=enums.ParseMode.MARKDOWN,
)
except MessageTooLong:
await message.edit_text(
"<code>Output is too long... Pasting to rentry...</code>"
)
try:
rentry_url, edit_code = await rentry_paste(
text=response.text, return_edit=True
)
except RuntimeError:
await message.edit_text(
"<b>Error:</b> <code>Failed to paste to rentry</code>"
)
return
await client.send_message(
"me",
f"Here's your edit code for Url: {rentry_url}\nEdit code: <code>{edit_code}</code>",
disable_web_page_preview=True,
)
await message.edit_text(
f"<b>Output:</b> {rentry_url}\n<b>Note:</b> <code>Edit Code has been sent to your saved messages</code>",
disable_web_page_preview=True,
)
except Exception as e:
await message.edit_text(f"An error occurred: {format_exc(e)}")
modules_help["gemini"] = {
"gemini [prompt]*": "Ask questions with Gemini Ai",
}
+47
View File
@@ -0,0 +1,47 @@
# Dragon-Userbot - telegram userbot
# Copyright (C) 2020-present Dragon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
@Client.on_message(filters.command(["google", "g"], prefix) & filters.me)
async def webshot(_, message: Message):
user_request = " ".join(message.command[1:])
if user_request == "":
if message.reply_to_message:
reply_user_request = message.reply_to_message.text
request = reply_user_request.replace(" ", "+")
full_request = f"https://lmgtfy.app/?s=g&iie=1&q={request}"
await message.edit(
f"<a href={full_request}>{reply_user_request}</a>",
disable_web_page_preview=True,
)
else:
request = user_request.replace(" ", "+")
full_request = f"https://lmgtfy.app/?s=g&iie=1&q={request}"
await message.edit(
f"<a href={full_request}>{user_request}</a>", disable_web_page_preview=True
)
modules_help["google"] = {
"google [request]": "To teach the interlocutor to use Google. Request isn't required."
}
+93
View File
@@ -0,0 +1,93 @@
import random
import asyncio
from pyrogram import Client, filters
from pyrogram.types import Message
from pyrogram.errors.exceptions.flood_420 import FloodWait
from utils.misc import modules_help, prefix
R = "❤️"
W = "🤍"
heart_list = [
W * 9,
W * 2 + R * 2 + W + R * 2 + W * 2,
W + R * 7 + W,
W + R * 7 + W,
W + R * 7 + W,
W * 2 + R * 5 + W * 2,
W * 3 + R * 3 + W * 3,
W * 4 + R + W * 4,
W * 9,
]
joined_heart = "\n".join(heart_list)
heartlet_len = joined_heart.count(R)
SLEEP = 0.1
async def _wrap_edit(message: Message, text: str):
"""Floodwait-safe utility wrapper for edit"""
try:
await message.edit(text)
except FloodWait as fl:
await asyncio.sleep(fl.x)
async def phase1(message: Message):
"""Big scroll"""
BIG_SCROLL = "🧡💛💚💙💜🖤🤎"
await _wrap_edit(message, joined_heart)
for heart in BIG_SCROLL:
await _wrap_edit(message, joined_heart.replace(R, heart))
await asyncio.sleep(SLEEP)
async def phase2(message: Message):
"""Per-heart randomiser"""
ALL = ["❤️"] + list("🧡💛💚💙💜🤎🖤") # don't include white heart
format_heart = joined_heart.replace(R, "{}")
for _ in range(5):
heart = format_heart.format(*random.choices(ALL, k=heartlet_len))
await _wrap_edit(message, heart)
await asyncio.sleep(SLEEP)
async def phase3(message: Message):
"""Fill up heartlet matrix"""
await _wrap_edit(message, joined_heart)
await asyncio.sleep(SLEEP * 2)
repl = joined_heart
for _ in range(joined_heart.count(W)):
repl = repl.replace(W, R, 1)
await _wrap_edit(message, repl)
await asyncio.sleep(SLEEP)
async def phase4(message: Message):
"""Matrix shrinking"""
for i in range(7, 0, -1):
heart_matrix = "\n".join([R * i] * i)
await _wrap_edit(message, heart_matrix)
await asyncio.sleep(SLEEP)
@Client.on_message(filters.command("hearts", prefix) & filters.me)
async def hearts(client: Client, message: Message):
await phase1(message)
await phase2(message)
await phase3(message)
await phase4(message)
await asyncio.sleep(SLEEP * 3)
final_caption = " ".join(message.command[1:])
if not final_caption:
final_caption = "💕 by @moonuserbot"
await message.edit(final_caption)
modules_help["hearts"] = {
"hearts": "Heart animation. May cause floodwaits, use at your own risk!"
}
+83
View File
@@ -0,0 +1,83 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_module_help, with_reply
from utils.module import ModuleManager
module_manager = ModuleManager.get_instance()
@Client.on_message(filters.command(["help", "h"], prefix) & filters.me)
async def help_cmd(_, message: Message):
if not module_manager.help_navigator:
await message.edit("<b>Help system is not initialized yet. Please wait...</b>")
return
if len(message.command) == 1:
await module_manager.help_navigator.send_page(message)
elif message.command[1].lower() in modules_help:
await message.edit(format_module_help(message.command[1].lower(), prefix))
else:
command_name = message.command[1].lower()
module_found = False
for module_name, commands in modules_help.items():
for command in commands.keys():
if command.split()[0] == command_name:
cmd = command.split(maxsplit=1)
cmd_desc = commands[command]
module_found = True
return await message.edit(
f"<b>Help for command <code>{prefix}{command_name}</code></b>\n"
f"Module: {module_name} (<code>{prefix}help {module_name}</code>)\n\n"
f"<code>{prefix}{cmd[0]}</code>"
f"{' <code>' + cmd[1] + '</code>' if len(cmd) > 1 else ''}"
f" — <i>{cmd_desc}</i>",
)
if not module_found:
await message.edit(f"<b>Module or command {command_name} not found</b>")
@Client.on_message(filters.command(["pn", "pp", "pq"], prefix) & filters.me)
@with_reply
async def handle_navigation(_, message: Message):
if not module_manager.help_navigator:
await message.edit("<b>Help system is not initialized yet. Please wait...</b>")
return
reply_message = message.reply_to_message
if reply_message and "Help Page No:" in message.reply_to_message.text:
cmd = message.command[0].lower()
if cmd == "pn":
if module_manager.help_navigator.next_page():
await module_manager.help_navigator.send_page(reply_message)
return await message.delete()
await message.edit("No more pages available.")
elif cmd == "pp":
if module_manager.help_navigator.prev_page():
await module_manager.help_navigator.send_page(reply_message)
return await message.delete()
return await message.edit("This is the first page.")
elif cmd == "pq":
await reply_message.delete()
return await message.edit("Help closed.")
modules_help["help"] = {
"help [module/command name]": "Get common/module/command help",
"pn/pp/pq": "Navigate through help pages"
+ " (pn: next page, pp: previous page, pq: quit help)",
}
+226
View File
@@ -0,0 +1,226 @@
import os
import io
import time
import aiohttp
import asyncio
import logging
from PIL import Image
from pyrogram import filters, Client, enums
from pyrogram.types import Message
from concurrent.futures import ThreadPoolExecutor
from utils.db import db
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
async def query_huggingface(payload):
api_key = db.get("custom.hf", "api_key", None)
model = db.get("custom.hf", "current_model", None)
if not api_key:
raise ValueError(
f"API key not set. Use {prefix}set_hf api <api_key> to set it."
)
if not model:
raise ValueError(
f"Model not set. Use {prefix}set_hf model <model_name> to set it."
)
api_url = f"https://api-inference.huggingface.co/models/{model}"
headers = {"Authorization": f"Bearer {api_key}"}
timeout = aiohttp.ClientTimeout(total=120)
start_time = time.time()
retries = 3
for attempt in range(1, retries + 1):
try:
async with aiohttp.ClientSession(timeout=timeout) as session:
async with session.post(
api_url, headers=headers, json=payload
) as response:
fetch_time = int((time.time() - start_time) * 1000)
if response.status != 200:
error_text = await response.text()
logger.error(f"API Error {response.status}: {error_text}")
return None, fetch_time
return await response.read(), fetch_time
except asyncio.TimeoutError:
logger.error(f"TimeoutError: Attempt {attempt}/{retries} timed out.")
if attempt == retries:
raise
except asyncio.CancelledError:
logger.error(
"Request was cancelled. Ensure the task is not being forcefully terminated."
)
raise
except aiohttp.ClientError as e:
logger.error(f"Network Error: {e}")
if attempt == retries:
raise
finally:
await asyncio.sleep(2)
async def save_image(image_bytes, path):
loop = asyncio.get_event_loop()
with ThreadPoolExecutor() as pool:
await loop.run_in_executor(
pool, lambda: Image.open(io.BytesIO(image_bytes)).save(path)
)
@Client.on_message(filters.command(["set_hf"], prefix) & filters.me)
async def manage_huggingface(_, message: Message):
"""Manage Hugging Face API key and models."""
subcommand = message.command[1].lower() if len(message.command) > 1 else None
arg = message.command[2] if len(message.command) > 2 else None
if subcommand == "api":
if arg:
db.set("custom.hf", "api_key", arg)
return await message.edit_text(
f"Hugging Face API key set successfully.\nAPI Key: {arg}"
)
return await message.edit_text(f"Usage: {prefix}hf api <api_key>")
if subcommand == "model":
if arg:
models = db.get("custom.hf", "models", [])
if arg not in models:
models.append(arg)
db.set("custom.hf", "models", models)
db.set("custom.hf", "current_model", arg)
return await message.edit_text(
f"Model '{arg}' added and set as the current model."
)
return await message.edit_text(f"Usage: {prefix}hf model <model_name>")
if subcommand == "select":
models = db.get("custom.hf", "models", [])
if arg and arg.lower() == "all":
db.set("custom.hf", "current_model", "all")
model_list = "\n".join([f"*{i + 1}. {m}" for i, m in enumerate(models)])
return await message.edit_text(
f"All models selected:\n<code>{model_list}</code>\n\n"
f"Images will be generated from all models."
)
if arg:
try:
index = int(arg) - 1
if 0 <= index < len(models):
db.set("custom.hf", "current_model", models[index])
return await message.edit_text(f"Model set to '{models[index]}'.")
return await message.edit_text("Invalid model number.")
except ValueError:
return await message.edit_text(
"Invalid model number. Use a valid integer."
)
return await message.edit_text(f"Usage: {prefix}hf select <model_number|all>")
if subcommand == "delete" and arg:
try:
index = int(arg) - 1
models = db.get("custom.hf", "models", [])
if 0 <= index < len(models):
removed_model = models.pop(index)
db.set("custom.hf", "models", models)
if db.get("custom.hf", "current_model") == removed_model:
db.set(
"custom.hf", "current_model", models[0] if models else "None"
)
return await message.edit_text(f"Model '{removed_model}' deleted.")
return await message.edit_text("Invalid model number.")
except ValueError:
return await message.edit_text("Invalid model number. Use a valid integer.")
api_key = db.get("custom.hf", "api_key", None)
models = db.get("custom.hf", "models", [])
current_model = db.get("custom.hf", "current_model", "Not set")
model_list = "\n".join(
[
f"{'*' if m == current_model or current_model == 'all' else ''}{i + 1}. {m}"
for i, m in enumerate(models)
]
)
settings = (
f"<b>Hugging Face settings:</b>\n"
f"<b>API Key:</b>\n<code>{api_key if api_key else 'Not set'}</code>\n\n"
f"<b>Available Models:</b>\n<code>{model_list}</code>"
)
usage_message = (
f"{settings}\n\n<b>Usage:</b>\n"
f"<code>{prefix}set_hf</code> <code>api</code>, <code>model</code>, <code>select</code>, <code>delete</code>, <code>select all</code>"
)
await message.edit_text(usage_message)
@Client.on_message(filters.command(["hf", "hface", "huggingface"], prefix))
async def imgflux_(_, message: Message):
prompt = message.text.split(" ", 1)[1] if len(message.command) > 1 else None
if not prompt:
usage_message = (
f"<b>Usage:</b> <code>{prefix}{message.command[0]} [custom prompt]</code>"
)
return await (
message.edit_text if message.from_user.is_self else message.reply_text
)(usage_message)
processing_message = await (
message.edit_text if message.from_user.is_self else message.reply_text
)("Processing...")
try:
current_model = db.get("custom.hf", "current_model", None)
models = db.get("custom.hf", "models", [])
models_to_use = models if current_model == "all" else [current_model]
generated_images = []
for model in models_to_use:
db.set("custom.hf", "current_model", model)
payload = {"inputs": prompt}
image_bytes, fetch_time = await query_huggingface(payload)
if not image_bytes:
logger.warning(f"Failed to fetch image for model: {model}")
continue
image_path = f"hf_flux_gen_{model.replace('/', '_')}.jpg"
await save_image(image_bytes, image_path)
generated_images.append((image_path, model, fetch_time))
if not generated_images:
return await processing_message.edit_text(
"Failed to generate an image for all models."
)
for image_path, model_name, fetch_time in generated_images:
caption = (
f"**Model:**\n> {model_name}\n"
f"**Prompt used:**\n> {prompt}\n\n"
f"**Fetching Time:** {fetch_time} ms"
)
await message.reply_photo(
image_path, caption=caption, parse_mode=enums.ParseMode.MARKDOWN
)
os.remove(image_path)
except Exception as e:
logger.error(f"Unexpected Error: {e}")
await processing_message.edit_text(format_exc(e))
finally:
await processing_message.delete()
modules_help["huggingface"] = {
"hf [prompt]*": "Generate an AI image using Hugging Face model(s).",
"set_hf <api>*": "Set the Hugging Face API key.",
"set_hf model <model_name>*": "Add and set a Hugging Face model.",
"set_hf select <model_number|all>*": "Select a specific model or all models for use.",
"set_hf delete <model_number>*": "Delete a model from the list.",
}
+88
View File
@@ -0,0 +1,88 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, enums, filters
from pyrogram.types import Message, MessageOriginHiddenUser
from utils.misc import modules_help, prefix
@Client.on_message(filters.command("id", prefix) & filters.me)
async def ids(_, message: Message):
text = "\n".join(
[
f"Chat ID: `{message.chat.id}`",
f"Chat DC ID: `{message.chat.dc_id}`\n",
f"Message ID: `{message.id}`",
(
f"Your ID: `{message.from_user.id}`"
if message.from_user
else f"Channel/Group ID: `{message.sender_chat.id}`"
),
(
f"Your DC ID: `{message.from_user.dc_id}`"
if message.from_user
else f"Channel/Group ID: `{message.sender_chat.id}`"
),
]
)
if rtm := message.reply_to_message:
# print(rtm)
text += f"\n\nReplied Message ID: `{rtm.id}`"
if user := rtm.from_user:
text = "\n".join(
[
text,
f"Replied User ID: `{user.id}`",
f"Replied User DC ID: `{user.dc_id}`",
]
)
else:
text = "\n".join(
[
text,
f"Replied Chat ID: `{rtm.sender_chat.id}`",
f"Replied Chat DC ID: `{rtm.sender_chat.dc_id}`",
]
)
if rtm.forward_origin and rtm.forward_origin.date:
if isinstance(rtm.forward_origin, MessageOriginHiddenUser):
text = "\n".join(
[
text,
"\nForwarded from a hidden user.",
]
)
elif ffc := rtm.forward_origin.sender_user:
text = "\n".join(
[
text,
f"\nForwarded Message ID: `{getattr(rtm.forward_origin, 'message_id', None)}`",
f"Forwarded from Chat ID: `{ffc.id}`",
f"Forwarded from Chat DC ID: `{ffc.dc_id}`",
]
)
await message.edit("**__" + text + "__**", parse_mode=enums.ParseMode.MARKDOWN)
modules_help["id"] = {
"id": "simply run or reply to message",
}
+44
View File
@@ -0,0 +1,44 @@
import asyncio
import os
from datetime import datetime
from pyrogram import Client, filters
from pyrogram.raw import functions
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
@Client.on_message(filters.command("joindate", prefix) & filters.me)
async def joindate(client: Client, message: Message):
await message.edit(f"<b>One moment...</b>")
members = []
cgetmsg = await client.get_messages(message.chat.id, 1)
async for m in client.iter_chat_members(message.chat.id):
members.append(
(
m.user.first_name,
m.joined_date or cgetmsg.date,
)
)
members.sort(key=lambda member: member[1])
with open("joined_date.txt", "w", encoding="utf8") as f:
f.write("Join Date First Name\n")
for member in members:
f.write(
str(datetime.fromtimestamp(member[1]).strftime("%y-%m-%d %H:%M"))
+ f" {member[0]}\n"
)
await message.delete()
await client.send_document(message.chat.id, "joined_date.txt")
os.remove("joined_date.txt")
modules_help["joindate"] = {
"joindate": "Get a list of all chat members and sort them by the date they joined the group"
}
+22
View File
@@ -0,0 +1,22 @@
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
import asyncio, random
@Client.on_message(filters.command("kokodrilo", prefix) & filters.me)
async def kokodrilo_explodando(_, message: Message):
amount = 1
if len(message.command) > 1:
amount = int(message.command[1])
for _ in range(amount):
await message.edit("🐊")
await asyncio.sleep(random.uniform(1, 2.5))
await message.edit("💥")
await asyncio.sleep(1.8)
modules_help["kokodrilo_explodando"] = {
"kokodrilo [number of explosions]": "<b>kOkOdRiLo ExPlOrAdO</b>",
}
+37
View File
@@ -0,0 +1,37 @@
# Dragon-Userbot - telegram userbot
# Copyright (C) 2020-present Dragon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import asyncio
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
@Client.on_message(filters.command(["leave_chat", "lc"], prefix) & filters.me)
async def leave_chat(_, message: Message):
if message.chat.type != "private":
await message.edit("<b>Goodbye...</b>")
await asyncio.sleep(3)
await message.chat.leave()
else:
await message.edit("<b>Not supported in private chats</b>")
modules_help["leave_chat"] = {
"leave_chat": "Quit chat",
}
+340
View File
@@ -0,0 +1,340 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import hashlib
import os
import shutil
import subprocess
import sys
import requests
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import restart
from utils.db import db
BASE_PATH = os.path.abspath(os.getcwd())
CATEGORIES = [
"ai",
"dl",
"admin",
"anime",
"fun",
"images",
"info",
"misc",
"music",
"news",
"paste",
"rev",
"tts",
"utils",
]
@Client.on_message(filters.command(["modhash", "mh"], prefix) & filters.me)
async def get_mod_hash(_, message: Message):
if len(message.command) == 1:
return
url = message.command[1].lower()
resp = requests.get(url)
if not resp.ok:
await message.edit(
f"<b>Troubleshooting with downloading module <code>{url}</code></b>"
)
return
await message.edit(
f"<b>Module hash: <code>{hashlib.sha256(resp.content).hexdigest()}</code>\n"
f"Link: <code>{url}</code>\nFile: <code>{url.split('/')[-1]}</code></b>",
)
@Client.on_message(filters.command(["loadmod", "lm"], prefix) & filters.me)
async def loadmod(_, message: Message):
if (
not (
message.reply_to_message
and message.reply_to_message.document
and message.reply_to_message.document.file_name.endswith(".py")
)
and len(message.command) == 1
):
await message.edit("<b>Specify module to download</b>")
return
if len(message.command) > 1:
await message.edit("<b>Fetching module...</b>")
url = message.command[1].lower()
if url.startswith(
"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/"
):
module_name = url.split("/")[-1].split(".")[0]
elif "." not in url:
module_name = url.lower()
try:
f = requests.get(
"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/full.txt"
).text
except Exception:
return await message.edit("Failed to fetch custom modules list")
modules_dict = {line.split("/")[-1].split()[0]: line.strip() for line in f.splitlines()}
if module_name in modules_dict:
url = f"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/{modules_dict[module_name]}.py"
else:
await message.edit(
f"<b>Module <code>{module_name}</code> is not found</b>"
)
return
else:
modules_hashes = requests.get(
"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/modules_hashes.txt"
).text
resp = requests.get(url)
if not resp.ok:
await message.edit(
f"<b>Troubleshooting with downloading module <code>{url}</code></b>",
)
return
if hashlib.sha256(resp.content).hexdigest() not in modules_hashes:
return await message.edit(
"<b>Only <a href=https://github.com/The-MoonTg-project/custom_modules/tree/main/modules_hashes.txt>"
"verified</a> modules or from the official "
"<a href=https://github.com/The-MoonTg-project/custom_modules>"
"custom_modules</a> repository are supported!</b>",
disable_web_page_preview=True,
)
module_name = url.split("/")[-1].split(".")[0]
resp = requests.get(url)
if not resp.ok:
await message.edit(f"<b>Module <code>{module_name}</code> is not found</b>")
return
if not os.path.exists(f"{BASE_PATH}/modules/custom_modules"):
os.mkdir(f"{BASE_PATH}/modules/custom_modules")
with open(f"./modules/custom_modules/{module_name}.py", "wb") as f:
f.write(resp.content)
else:
file_name = await message.reply_to_message.download()
module_name = message.reply_to_message.document.file_name[:-3]
with open(file_name, "rb") as f:
content = f.read()
modules_hashes = requests.get(
"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/modules_hashes.txt"
).text
if hashlib.sha256(content).hexdigest() not in modules_hashes:
os.remove(file_name)
return await message.edit(
"<b>Only <a href=https://github.com/The-MoonTg-project/custom_modules/tree/main/modules_hashes.txt>"
"verified</a> modules or from the official "
"<a href=https://github.com/The-MoonTg-project/custom_modules>"
"custom_modules</a> repository are supported!</b>",
disable_web_page_preview=True,
)
os.rename(file_name, f"./modules/custom_modules/{module_name}.py")
all_modules = db.get("custom.modules", "allModules", [])
if module_name not in all_modules:
all_modules.append(module_name)
db.set("custom.modules", "allModules", all_modules)
await message.edit(
f"<b>The module <code>{module_name}</code> is loaded!\nRestarting...</b>"
)
db.set(
"core.updater",
"restart_info",
{
"type": "restart",
"chat_id": message.chat.id,
"message_id": message.id,
},
)
restart()
@Client.on_message(filters.command(["unloadmod", "ulm"], prefix) & filters.me)
async def unload_mods(_, message: Message):
if len(message.command) <= 1:
return
module_name = message.command[1].lower()
if module_name.startswith(
"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/"
):
module_name = module_name.split("/")[-1].split(".")[0]
if os.path.exists(f"{BASE_PATH}/modules/custom_modules/{module_name}.py"):
os.remove(f"{BASE_PATH}/modules/custom_modules/{module_name}.py")
if module_name == "musicbot":
subprocess.run(
[sys.executable, "-m", "pip", "uninstall", "-y", "requirements.txt"],
cwd=f"{BASE_PATH}/musicbot",
)
shutil.rmtree(f"{BASE_PATH}/musicbot")
all_modules = db.get("custom.modules", "allModules", [])
if module_name in all_modules:
all_modules.remove(module_name)
db.set("custom.modules", "allModules", all_modules)
await message.edit(
f"<b>The module <code>{module_name}</code> removed!\nRestarting...</b>"
)
db.set(
"core.updater",
"restart_info",
{
"type": "restart",
"chat_id": message.chat.id,
"message_id": message.id,
},
)
restart()
elif os.path.exists(f"{BASE_PATH}/modules/{module_name}.py"):
await message.edit(
"<b>It is forbidden to remove built-in modules, it will disrupt the updater</b>"
)
else:
await message.edit(f"<b>Module <code>{module_name}</code> is not found</b>")
@Client.on_message(filters.command(["loadallmods", "lmall"], prefix) & filters.me)
async def load_all_mods(_, message: Message):
await message.edit("<b>Fetching info...</b>")
if not os.path.exists(f"{BASE_PATH}/modules/custom_modules"):
os.mkdir(f"{BASE_PATH}/modules/custom_modules")
try:
f = requests.get(
"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/full.txt"
).text
except Exception:
return await message.edit("Failed to fetch custom modules list")
modules_list = f.splitlines()
await message.edit("<b>Loading modules...</b>")
for module_name in modules_list:
url = f"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/{module_name}.py"
resp = requests.get(url)
if not resp.ok:
continue
with open(
f"./modules/custom_modules/{module_name.split('/')[1]}.py", "wb"
) as f:
f.write(resp.content)
await message.edit(
f"<b>Successfully loaded new modules: {len(modules_list)}\nRestarting...</b>",
)
db.set(
"core.updater",
"restart_info",
{
"type": "restart",
"chat_id": message.chat.id,
"message_id": message.id,
},
)
restart()
@Client.on_message(filters.command(["unloadallmods", "ulmall"], prefix) & filters.me)
async def unload_all_mods(_, message: Message):
await message.edit("<b>Fetching info...</b>")
if not os.path.exists(f"{BASE_PATH}/modules/custom_modules"):
return await message.edit("<b>You don't have any modules installed</b>")
shutil.rmtree(f"{BASE_PATH}/modules/custom_modules")
db.set("custom.modules", "allModules", [])
await message.edit("<b>Successfully unloaded all modules!\nRestarting...</b>")
db.set(
"core.updater",
"restart_info",
{
"type": "restart",
"chat_id": message.chat.id,
"message_id": message.id,
},
)
restart()
@Client.on_message(filters.command(["updateallmods"], prefix) & filters.me)
async def updateallmods(_, message: Message):
await message.edit("<b>Updating modules...</b>")
if not os.path.exists(f"{BASE_PATH}/modules/custom_modules"):
os.mkdir(f"{BASE_PATH}/modules/custom_modules")
modules_installed = list(os.walk("modules/custom_modules"))[0][2]
if not modules_installed:
return await message.edit("<b>You don't have any modules installed</b>")
for module_name in modules_installed:
if not module_name.endswith(".py"):
continue
try:
f = requests.get(
"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/full.txt"
).text
except Exception:
return await message.edit("Failed to fetch custom modules list")
modules_dict = {line.split("/")[-1].split()[0]: line.strip() for line in f.splitlines()}
if module_name in modules_dict:
resp = requests.get(
f"https://raw.githubusercontent.com/The-MoonTg-project/custom_modules/main/{modules_dict[module_name]}.py"
)
if not resp.ok:
modules_installed.remove(module_name)
continue
with open(f"./modules/custom_modules/{module_name}", "wb") as f:
f.write(resp.content)
await message.edit(f"<b>Successfully updated {len(modules_installed)} modules</b>")
modules_help["loader"] = {
"loadmod [module_name]*": "Download module.\n"
"Only modules from the official custom_modules repository and proven "
"modules whose hashes are in modules_hashes.txt are supported",
"unloadmod [module_name]*": "Delete module",
"modhash [link]*": "Get module hash by link",
"loadallmods": "Load all custom modules (use it at your own risk)",
"unloadallmods": "Unload all custom modules",
"updateallmods": "Update all custom modules"
"\n\n* - required argument"
"\n <b>short cmds:</b>"
"\n loadmod - lm"
"\n unloadmod - ulm"
"\n modhash - mh"
"\n loadallmods - lmall"
"\n unloadallmods - ulmall",
}
+51
View File
@@ -0,0 +1,51 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
import os
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help
from utils.scripts import prefix, import_library, with_reply
import_library("markitdown")
from markitdown import MarkItDown
@Client.on_message(filters.command(["markitdown", "mkdn"], prefix) & filters.me)
@with_reply
async def markitdown(client: Client, message: Message):
if message.reply_to_message.document:
await message.edit("Converting to Markdown...")
file = await message.reply_to_message.download()
file_name = (message.reply_to_message.document.file_name).split(".")[0] + ".md"
markitdown = MarkItDown()
result = markitdown.convert(file)
with open(file_name, "w") as f:
f.write(result.text_content)
await message.edit("Uploading...")
await client.send_document(
message.chat.id, file_name, reply_to_message_id=message.reply_to_message.id
)
os.remove(file)
os.remove(file_name)
await message.delete()
else:
await message.edit("Reply to a document to convert it to Markdown.")
modules_help["markitdown"] = {"markitdown": "Convert a document to Markdown."}
+72
View File
@@ -0,0 +1,72 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.types import Message
from pyrogram.types.user_and_chats.user import Link
from utils.misc import modules_help, prefix
def custom_mention(user, custom_text):
return Link(
f"tg://user?id={user.id}",
custom_text,
user._client.parse_mode,
)
@Client.on_message(filters.command("mention", prefix) & filters.me)
async def example_edit(client: Client, message: Message):
chat_id = message.chat.id
if message.reply_to_message and not len(message.text.split()) > 1:
user = message.reply_to_message.from_user
custom_text = (
message.text.split(maxsplit=1)[1] if len(message.text.split()) > 1 else None
)
if custom_text:
await message.edit(custom_mention(user, custom_text))
else:
await message.delete()
await client.send_message(chat_id, user.mention)
else:
if len(message.text.split()) > 1:
user_id = message.text.split()[1]
if user_id.isdigit():
text = (
message.text.split(maxsplit=2)[2]
if len(message.text.split()) > 2
else None
)
if text:
men = Link(f"tg://user?id={user_id}", text, client.parse_mode)
else:
men = (await client.get_users(user_id)).mention
await message.edit(men)
else:
await message.edit("Invalid user_id")
await message.delete()
else:
await message.edit("Reply to a message or provide a user_id")
await message.delete()
modules_help["mention"] = {
"mention": "Mention the user you replied to.",
"mention [custom_text]": "Mention the user you replied to with custom text.",
"mention [user_id] [custom_text]": "Mention a user by their user_id with custom text.",
"mention [user_id]": "Mention a user by their user_id.",
}
+61
View File
@@ -0,0 +1,61 @@
# original module https://raw.githubusercontent.com/KeyZenD/modules/master/MirrorFlipV2.py | t.me/the_kzd
import os
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import import_library
PIL = import_library("PIL", "pillow")
from PIL import Image, ImageOps
async def make(client, message, o):
reply = message.reply_to_message
if reply.photo or reply.sticker:
if reply.photo:
downloads = await client.download_media(reply.photo.file_id)
else:
downloads = await client.download_media(reply.sticker.file_id)
path = f"{downloads}"
img = Image.open(path)
await message.delete()
w, h = img.size
if o in [1, 2]:
if o == 2:
img = ImageOps.mirror(img)
part = img.crop([0, 0, w // 2, h])
img = ImageOps.mirror(img)
else:
if o == 4:
img = ImageOps.flip(img)
part = img.crop([0, 0, w, h // 2])
img = ImageOps.flip(img)
img.paste(part, (0, 0))
img.save(path)
if reply.photo:
return await reply.reply_photo(photo=path)
elif reply.sticker:
return await reply.reply_sticker(sticker=path)
os.remove(path)
return await message.edit(
"<b>Need to answer the photo/sticker</b>", parse_mode=enums.ParseMode.HTML
)
@Client.on_message(filters.command(["ll", "rr", "dd", "uu"], prefix) & filters.me)
async def mirror_flip(client: Client, message: Message):
await message.edit("<b>Processing...</b>", parse_mode=enums.ParseMode.HTML)
param = {"ll": 1, "rr": 2, "dd": 3, "uu": 4}[message.command[0]]
await make(client, message, param)
modules_help["mirror_flip"] = {
"ll [reply on photo or sticker]*": "reflects the left side",
"rr [reply on photo or sticker]*": "reflects the right side",
"uu [reply on photo or sticker]*": "reflects the top",
"dd [reply on photo or sticker]*": "reflects the bottom",
}
+59
View File
@@ -0,0 +1,59 @@
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from os import listdir
# noinspection PyUnresolvedReferences
from utils.misc import modules_help, prefix
# noinspection PyUnresolvedReferences
from utils.scripts import format_exc
@Client.on_message(filters.command(["lback"], prefix) & filters.me)
async def backup_database_cmd(_: Client, message: Message):
"""
Backup the database.
"""
if len(message.command) == 1:
await message.edit("[😇] I think you didn't specify the name of the bot.")
return
await message.edit_text(
"<b>I'm copying the database...</b>", parse_mode=enums.ParseMode.HTML
)
try:
name = message.command[1].lower()
folders = listdir("/root/")
if name not in folders:
await message.edit("[😇] There is no such bot in the root folder.")
return
folder = listdir("/root/" + name)
for file in folder:
if file.endswith((".db", ".sqlite", ".sqlite3")):
await message.reply_document(
document="/root/" + name + "/" + file,
caption="<code>Bot Database <b>" + name + "</b></code>",
parse_mode=enums.ParseMode.HTML,
)
return await message.delete()
folder = listdir("/root/" + name + "/assets")
for file in folder:
if file.endswith((".db", ".sqlite", ".sqlite3")):
await message.reply_document(
document="/root/" + name + "/assets/" + file,
caption="<code>Bot Database <b>" + name + "</b></code>",
parse_mode=enums.ParseMode.HTML,
)
return await message.delete()
await message.edit("[😇] Database not found.")
except Exception as ex:
await message.edit_text(
"Failed to back up the database!\n\n" f"{format_exc(ex)}",
parse_mode=enums.ParseMode.HTML,
)
modules_help["autobackup"] = {
"lback [name]*": "<b>Backup database from folder</b>",
"lbackall": "<b>Backup all databases</b>",
}
+177
View File
@@ -0,0 +1,177 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.types import Message
from pyrogram.errors import MessageTooLong
from utils.misc import modules_help, prefix
from utils.db import db
def addtrg(channel_id):
channel_ids = db.get("custom.autofwd", "chatto", default=[])
if channel_id not in channel_ids:
channel_ids.append(channel_id)
db.set("custom.autofwd", "chatto", channel_ids)
def rmtrg(channel_id):
channel_ids = db.get("custom.autofwd", "chatto", default=[])
if channel_id in channel_ids:
channel_ids.remove(channel_id)
db.set("custom.autofwd", "chatto", channel_ids)
def addsrc(channel_id):
channel_ids = db.get("custom.autofwd", "chatsrc", default=[])
if channel_id not in channel_ids:
channel_ids.append(channel_id)
db.set("custom.autofwd", "chatsrc", channel_ids)
def rmsrc(channel_id):
channel_ids = db.get("custom.autofwd", "chatsrc", default=[])
if channel_id in channel_ids:
channel_ids.remove(channel_id)
db.set("custom.autofwd", "chatsrc", channel_ids)
def getfwd_data():
source_chats = db.get("custom.autofwd", "chatsrc")
target_chats = db.get("custom.autofwd", "chatto")
return source_chats, target_chats
@Client.on_message(filters.command(["addfwd_src", "addfwd_to"], prefix) & filters.me)
async def addfwd(_, message: Message):
if message.command[0] == "addfwd_src":
if len(message.command) > 1:
channel_id = message.text.split(maxsplit=1)[1]
if not channel_id.startswith("-100"):
channel_id = "-100" + channel_id
# chat id should be integer
if not channel_id.isdigit():
try:
channel_id = int(channel_id)
except Exception:
return await message.edit_text("Chat id should be in integer")
addsrc(channel_id=channel_id)
await message.edit_text(
f"Auto Forwarding Enabled for Chat with id: <code>{channel_id}</code>"
)
else:
await message.edit_text("Chat id not provided!")
return
elif message.command[0] == "addfwd_to":
if len(message.command) > 1:
channel_id = message.text.split(maxsplit=1)[1]
if not channel_id.startswith("-100"):
channel_id = "-100" + channel_id
# chat id should be integer
if not channel_id.isdigit():
try:
channel_id = int(channel_id)
except Exception:
return await message.edit_text("Chat id should be in integer")
addtrg(channel_id=channel_id)
await message.edit_text(
f"Auto Forwarding Enabled to Chat with id: <code>{channel_id}</code>"
)
else:
await message.edit_text("Chat id not provided!")
return
@Client.on_message(filters.command(["delfwd_src", "delfwd_to"], prefix) & filters.me)
async def delfwd(_, message: Message):
if message.command[0] == "delfwd_src":
if len(message.command) > 1:
channel_id = message.text.split(maxsplit=1)[1]
if not channel_id.startswith("-100"):
channel_id = "-100" + channel_id
# chat id should be integer
if not channel_id.isdigit():
try:
channel_id = int(channel_id)
except Exception:
return await message.edit_text("Chat id should be in integer")
rmsrc(channel_id=channel_id)
await message.edit_text(
f"Auto Forwarding Disabled for Chat with id: <code>{channel_id}</code>"
)
else:
await message.edit_text("Chat id not provided!")
return
elif message.command[0] == "delfwd_to":
if len(message.command) > 1:
channel_id = message.text.split(maxsplit=1)[1]
if not channel_id.startswith("-100"):
channel_id = "-100" + channel_id
# chat id should be integer
if not channel_id.isdigit():
try:
channel_id = int(channel_id)
except Exception:
return await message.edit_text("Chat id should be in integer")
rmtrg(channel_id=channel_id)
await message.edit_text(
f"Auto Forwarding Disabled to Chat with id: <code>{channel_id}</code>"
)
else:
await message.edit_text("Chat id not provided!")
return
@Client.on_message(filters.command("autofwd", prefix) & filters.me)
async def autofwd(_, message: Message):
source_chats, target_chats = getfwd_data()
return await message.edit_text(
f"Source Chats: {source_chats}\nTarget Chats: {target_chats}"
)
@Client.on_message(filters.channel | filters.group)
async def autofwd_main(client: Client, message: Message):
chat_id = message.chat.id
source_chats = db.get("custom.autofwd", "chatsrc")
target_chats = db.get("custom.autofwd", "chatto")
if source_chats is not None and chat_id in source_chats:
if target_chats is not None:
for chat in target_chats:
try:
await message.copy(chat)
except Exception as e:
try:
await client.send_message(
"me",
f"Auto Forwarding Failed for Chat with id: <code>{chat_id}</code> to <code>{chat}</code>\n\n{e}",
)
except MessageTooLong:
await client.send_message(
"me",
f"Auto Forwarding Failed for Chat with id: <code>{chat_id}</code> to <code>{chat}</code>, Please check logs!",
)
modules_help["autofwd"] = {
"autofwd": "Retrieve Data of auto fwd",
"addfwd_src [channel_id]*": "Enable auto forwarding for a channel",
"addfwd_to [channel_id]*": "Enable auto forwarding to a channel",
"delfwd_src [channel_id]*": "Disable auto forwarding for a channel",
"delfwd_to [channel_id]*": "Disable auto forwarding to a channel",
}
+251
View File
@@ -0,0 +1,251 @@
import os
import shutil
from pyrogram import Client, filters, enums
from pyrogram.types import Message
# noinspection PyUnresolvedReferences
from utils.misc import modules_help, prefix
from utils.scripts import format_exc, restart
from utils.db import db
from utils import config
if config.db_type in ["mongodb", "mongo"]:
import bson
def dump_mongo(collections, path, db_):
for coll in collections:
with open(os.path.join(path, f"{coll}.bson"), "wb+") as f:
for doc in db_[coll].find():
f.write(bson.BSON.encode(doc))
def restore_mongo(path, db_):
for coll in os.listdir(path):
if coll.endswith(".bson"):
with open(os.path.join(path, coll), "rb+") as f:
db_[coll.split(".")[0]].insert_many(bson.decode_all(f.read()))
@Client.on_message(filters.command(["backup", "back"], prefix) & filters.me)
async def backup(client: Client, message: Message):
"""
Backup the database
"""
try:
if not os.path.exists("backups/"):
os.mkdir("backups/")
await message.edit(
"<b>Backing up database...</b>", parse_mode=enums.ParseMode.HTML
)
if config.db_type in ["mongo", "mongodb"]:
dump_mongo(db._database.list_collection_names(), "backups/", db._database)
return await message.edit(
f"<b>Database backed up to:</b> <code>backups/</code> folder",
parse_mode=enums.ParseMode.HTML,
)
else:
shutil.copy(config.db_name, f"backups/{config.db_name}")
await client.send_document(
"me",
caption=f"<b>Database backup complete!\nType: </b>"
f"<code>.restore</code> in response to this message to restore the database.",
document=f"backups/{config.db_name}",
parse_mode=enums.ParseMode.HTML,
)
return await message.edit(
"<b>Database backed up successfully! <code>(Check your favorites)</code></b>",
parse_mode=enums.ParseMode.HTML,
)
except Exception as e:
await message.edit(format_exc(e), parse_mode=enums.ParseMode.HTML)
@Client.on_message(filters.command(["restore", "res"], prefix) & filters.me)
async def restore(client: Client, message: Message):
"""
Restore the database
"""
try:
await message.edit(
"<b>Restoring database...</b>", parse_mode=enums.ParseMode.HTML
)
if config.db_type in ["mongo", "mongodb"]:
restore_mongo("backups/", db._database)
return await message.edit(
f"<b>Database restored from:</b> <code>backups/</code> folder",
parse_mode=enums.ParseMode.HTML,
)
else:
if not message.reply_to_message or not message.reply_to_message.document:
return await message.edit(
"<b>Reply to a document to restore the database.</b>",
parse_mode=enums.ParseMode.HTML,
)
elif not message.reply_to_message.document.file_name.casefold().endswith(
(".db", ".sqlite", ".sqlite3")
):
return await message.edit(
"<b>Reply to a database file to restore the database.</b>",
parse_mode=enums.ParseMode.HTML,
)
await message.reply_to_message.download(
f"backups/{message.reply_to_message.document.file_name}"
)
shutil.copy(
f"backups/{message.reply_to_message.document.file_name}", config.db_name
)
await message.edit(
"<b>Database restored successfully!</b>",
parse_mode=enums.ParseMode.HTML,
)
restart()
except Exception as e:
await message.edit(format_exc(e), parse_mode=enums.ParseMode.HTML)
@Client.on_message(filters.command(["backupmods", "bms"], prefix) & filters.me)
async def backupmods(client: Client, message: Message):
"""
Backup the modules
"""
try:
if not os.path.exists("backups/"):
os.mkdir("backups/")
await message.edit(
"<b>Backing up modules...</b>", parse_mode=enums.ParseMode.HTML
)
from utils.misc import modules_help
for mod in modules_help:
if os.path.isfile(f"modules/custom_modules/{mod}.py"):
f = open(f"backups/{mod}.py", "wb")
f.write(open(f"modules/custom_modules/{mod}.py", "rb").read())
await message.edit(
text=f"<b>All modules backed up to:</b> <code>backups/</code> folder",
parse_mode=enums.ParseMode.HTML,
)
except Exception as e:
await message.edit(format_exc(e), parse_mode=enums.ParseMode.HTML)
@Client.on_message(filters.command(["backupmod", "bm"], prefix) & filters.me)
async def backupmod(client: Client, message: Message):
"""
Backup the module
"""
try:
if not os.path.exists("backups/"):
os.mkdir("backups/")
from utils.misc import modules_help
try:
mod = message.text.split(maxsplit=1)[1].split(".")[0]
except:
return await message.edit(
f"<b>Usage:</b> <code>{prefix}backupmod [module]</code>",
parse_mode=enums.ParseMode.HTML,
)
await message.edit(
"<b>Backing up module...</b>", parse_mode=enums.ParseMode.HTML
)
if os.path.isfile(f"modules/custom_modules/{mod}.py"):
f = open(f"backups/{mod}.py", "wb")
f.write(open(f"modules/custom_modules/{mod}.py", "rb").read())
else:
return await message.edit(
f"<b>Module <code>{mod}</code> not found.</b>",
parse_mode=enums.ParseMode.HTML,
)
await message.reply_document(
document=f"backups/{mod}.py",
caption=f"<b>Module <code>{mod}</code> backed up to:</b> <code>backups/</code> folder",
parse_mode=enums.ParseMode.HTML,
)
except Exception as e:
await message.edit(format_exc(e), parse_mode=enums.ParseMode.HTML)
@Client.on_message(filters.command(["restoremod", "resmod"], prefix) & filters.me)
async def restoremod(client: Client, message: Message):
"""
Restore the module
"""
try:
if not os.path.exists("backups/"):
os.mkdir("backups/")
from utils.misc import modules_help
try:
mod = message.text.split(maxsplit=1)[1].split(".")[0]
except:
return await message.edit(
f"<b>Usage:</b> <code>{prefix}restoremod [module]</code>",
parse_mode=enums.ParseMode.HTML,
)
await message.edit(
"<b>Restoring module...</b>", parse_mode=enums.ParseMode.HTML
)
if os.path.isfile(f"backups/{mod}.py"):
f = open(f"modules/custom_modules/{mod}.py", "wb")
f.write(open(f"backups/{mod}.py", "rb").read())
else:
return await message.edit(
f"<b>Module <code>{mod}</code> not found.</b>",
parse_mode=enums.ParseMode.HTML,
)
await message.edit(
f"<b>Module <code>{mod}</code> restored successfully!</b>",
parse_mode=enums.ParseMode.HTML,
)
restart()
except Exception as e:
await message.edit(format_exc(e), parse_mode=enums.ParseMode.HTML)
@Client.on_message(filters.command(["restoremods", "resmods"], prefix) & filters.me)
async def restoremods(client: Client, message: Message):
"""
Restore the modules
"""
try:
if not os.path.exists("backups/"):
os.mkdir("backups/")
await message.edit(
"<b>Restoring modules...</b>", parse_mode=enums.ParseMode.HTML
)
for mod in os.listdir("backups/"):
if mod.endswith(".py"):
if os.path.isfile(f"modules/{mod}"):
continue
f = open(f"modules/custom_modules/{mod}", "wb")
f.write(open(f"backups/{mod}", "rb").read())
await message.edit(
text=f"<b>All modules restored from:</b> <code>backups/</code> folder",
parse_mode=enums.ParseMode.HTML,
)
restart()
except Exception as e:
await message.edit(format_exc(e), parse_mode=enums.ParseMode.HTML)
modules_help["backup"] = {
"backup": f"<b>Backup database</b>",
"restore [reply]": f"<b>Restore database</b>",
"backupmod [name]": f"<b>Backup mod</b>",
"backupmods": f"<b>Backup all mods</b>",
"resmod [name]": f"<b>Restore mod</b>",
"resmods": f"<b>Restore all mods</b>",
}
+109
View File
@@ -0,0 +1,109 @@
from pyrogram import Client, filters
import requests
from utils.scripts import format_exc, import_library
from utils.misc import modules_help, prefix
pcp = import_library("pubchempy")
INATURALIST_API_URL = "https://api.inaturalist.org/v1/observations"
def get_marine_life_details(species_name):
params = {
"taxon_name": species_name,
"quality_grade": "research",
"iconic_taxa": "Mollusca,Fish,Crustacea",
"per_page": 1,
}
response = requests.get(INATURALIST_API_URL, params=params)
if response.status_code == 200:
data = response.json()
if data["total_results"] > 0:
observation = data["results"][0]
species = observation["taxon"]["name"]
common_name = observation["taxon"]["preferred_common_name"]
photo_url = (
observation["photos"][0]["url"]
if observation["photos"]
else "No photo available"
)
description = (
observation["description"]
if "description" in observation
else "No description available."
)
return {
"species": species,
"common_name": common_name,
"photo_url": photo_url,
"description": description,
}
else:
return {"error": "No marine life found for this species."}
else:
return {
"error": f"Error {response.status_code}: Unable to connect to iNaturalist API."
}
@Client.on_message(filters.command("camistry", prefix) & filters.me)
async def fetch_chemical_data_with_visual(_, message):
query = " ".join(message.text.split()[1:]) # Combine query words properly
try:
# Fetch chemical data by name
results = pcp.get_compounds(query, "name", record_type="3d")
if results:
compound = results[0]
# Send chemical information without SMILES structure
info = (
f"<b>Chemical Data for {compound.iupac_name}</b>\n\n"
f"<b>Molecular Formula:</b> <code>{compound.molecular_formula}</code>\n"
f"<b>Molecular Weight:</b> <code>{compound.molecular_weight}</code>\n"
f"<b>CID:</b> <code>{compound.cid}</code>\n"
f"<b>Synonyms:</b> <code>{', '.join(compound.synonyms[:5])}</code>\n"
)
await message.edit_text(info)
else:
await message.edit_text(f"No chemical data found for the query: '{query}'")
except pcp.PubChemHTTPError as http_err:
await message.edit_text(f"HTTP error occurred: {format_exc(http_err)}")
except Exception as e:
await message.edit_text(f"An error occurred: {format_exc(e)}")
@Client.on_message(filters.command("marinelife", prefix) & filters.me)
async def marine_life_command(_, message):
if len(message.command) < 2:
await message.edit_text(
f"Please specify a species name. Example: {prefix}marinelife dolphin"
)
return
species_name = " ".join(message.command[1:])
marine_life = get_marine_life_details(species_name)
if "error" in marine_life:
await message.edit_text(marine_life["error"])
else:
reply_text = (
f"<b>Species</b>: <code>{marine_life['species']}</code>\n"
f"<b>Common Name</b>: <code>{marine_life['common_name']}</code>\n"
f"<b>Description</b>: <code>{marine_life['description']}</code>\n"
f"<a href='{marine_life['photo_url']}'>Photo</a>"
)
await message.edit_text(reply_text)
modules_help["cama"] = {
"camistry [text]": " getting camicale info",
"marinelife [text]": " getting marinelife info",
}
+144
View File
@@ -0,0 +1,144 @@
import asyncio
import os
from pyrogram import Client, filters
from pyrogram.errors import (
FileReferenceExpired,
FileReferenceInvalid,
TopicDeleted,
TopicClosed,
)
from pyrogram.types import Message
from collections import defaultdict
from utils.db import db
from utils.misc import modules_help, prefix
mlog_enabled = filters.create(lambda _, __, ___: db.get("custom.mlog", "status", False))
# Media cache and processing tasks
user_media_cache = defaultdict(list)
media_processing_tasks = {}
# Helper to get group-specific data
def get_group_data(group_id):
return db.get(f"custom.mlog", str(group_id), {})
# Helper to update group-specific data
def update_group_data(group_id, data):
db.set(f"custom.mlog", str(group_id), data)
@Client.on_message(filters.command(["mlog"], prefix) & filters.me)
async def mlog(_, message: Message):
if len(message.command) < 2 or message.command[1].lower() not in ["on", "off"]:
return await message.edit(f"<b>Usage:</b> <code>{prefix}mlog [on/off]</code>")
status = message.command[1].lower() == "on"
db.set("custom.mlog", "status", status)
await message.edit(f"<b>Media logging is now {'enabled' if status else 'disabled'}</b>")
@Client.on_message(filters.command(["msetchat"], prefix) & filters.me)
async def set_chat(_, message: Message):
if len(message.command) < 2:
return await message.edit(f"<b>Usage:</b> <code>{prefix}msetchat [chat_id]</code>")
try:
chat_id = message.command[1]
chat_id = int("-100" + chat_id if not chat_id.startswith("-100") else chat_id)
db.set("custom.mlog", "chat", chat_id)
await message.edit(f"<b>Chat ID set to {chat_id}</b>")
except ValueError:
await message.edit("<b>Invalid chat ID</b>")
@Client.on_message(
mlog_enabled
& filters.incoming
& filters.private
& filters.media
& ~filters.me
& ~filters.bot
)
async def media_log(client: Client, message: Message):
user_id = message.from_user.id
user_media_cache[user_id].append(message)
if user_id not in media_processing_tasks:
media_processing_tasks[user_id] = asyncio.create_task(process_media(client, message.from_user))
async def process_media(client: Client, user):
await asyncio.sleep(5) # Wait to group incoming media
user_id = user.id
me = await client.get_me()
if user_id == me.id:
return
chat_id = db.get("custom.mlog", "chat")
if not chat_id:
return await client.send_message(
"me",
f"Media Logger is on, but no Chat ID is set. Use {prefix}msetchat to set it.",
)
group_data = get_group_data(chat_id)
user_topics = group_data.get("user_topics", {})
topic_id = user_topics.get(str(user_id)) # Fetch user's topic ID if it exists
if not topic_id:
topic = await client.create_forum_topic(chat_id, user.first_name)
topic_id = topic.id
user_topics[str(user_id)] = topic_id # Store topic ID for this user
update_group_data(chat_id, {"user_topics": user_topics})
m = await client.send_message(
chat_id=chat_id,
message_thread_id=topic_id,
text=f"<b>Chat Name:</b> {user.full_name}\n<b>User ID:</b> {user_id}\n<b>Username:</b> @{user.username or 'N/A'}\n<b>Phone No:</b> +{user.phone_number or 'N/A'}",
)
await m.pin()
messages_to_process = user_media_cache.pop(user_id, [])
for media_message in messages_to_process:
try:
await media_message.copy(chat_id=chat_id, message_thread_id=topic_id)
await asyncio.sleep(1) # Delay between sending media
except (FileReferenceExpired, FileReferenceInvalid):
# Handle self-destruct photos and video notes
await handle_self_destruct_media(client, media_message, chat_id, topic_id)
except TopicDeleted:
topic = await client.create_forum_topic(chat_id, user.first_name)
topic_id = topic.id
user_topics[str(user_id)] = topic_id # Update the new topic ID
update_group_data(chat_id, {"user_topics": user_topics})
await client.send_message(
chat_id=chat_id,
message_thread_id=topic_id,
text=f"<b>Chat Name:</b> {user.full_name}\n<b>User ID:</b> {user_id}\n<b>Username:</b> @{user.username or 'N/A'}\n<b>Phone No:</b> +{user.phone_number or 'N/A'}",
)
await handle_self_destruct_media(client, media_message, chat_id, topic_id)
except TopicClosed:
await client.reopen_forum_topic(chat_id=chat_id, topic_id=topic_id)
await media_message.copy(chat_id=chat_id, message_thread_id=topic_id)
media_processing_tasks.pop(user_id, None)
async def handle_self_destruct_media(client: Client, message: Message, chat_id: int, topic_id: int):
try:
# Download the self-destructing media
file_path = await message.download()
if message.photo:
await client.send_photo(chat_id, file_path, message_thread_id=topic_id)
elif message.video_note:
await client.send_video(chat_id, file_path, message_thread_id=topic_id)
os.remove(file_path) # Clean up after sending
except Exception as e:
print(f"Error handling self-destructing media: {e}")
modules_help["mlog"] = {
"mlog [on/off]": "Enable or disable media logging",
"msetchat [chat_id]": "Set the chat ID for media logging",
}
+90
View File
@@ -0,0 +1,90 @@
from pyrogram import Client, filters
from pyrogram.types import Message
import aiohttp
from datetime import datetime
from utils.misc import modules_help, prefix
# Aladhan API credentials
ALADHAN_API_URL = "https://api.aladhan.com/v1/timingsByCity"
DEFAULT_METHOD = 2 # Islamic Society of North America
DEFAULT_CITY = "Lahore"
DEFAULT_COUNTRY = "PK"
async def fetch_namaz_times(city_name: str, country_name: str) -> dict:
params = {"city": city_name, "country": country_name, "method": DEFAULT_METHOD}
async with aiohttp.ClientSession() as session:
try:
async with session.get(ALADHAN_API_URL, params=params) as response:
response.raise_for_status()
return await response.json()
except Exception as e:
return {"error": str(e)}
def format_time_12hr(time_str: str) -> str:
try:
# Split time into hours and minutes
hours, minutes = map(int, time_str.split(":"))
# Convert to 12-hour format
period = "AM" if hours < 12 else "PM"
if hours == 0:
hours = 12
elif hours > 12:
hours -= 12
elif hours == 12:
period = "PM"
return f"{hours}:{minutes:02d} {period}"
except Exception as e:
return f"Error formatting time: {str(e)}"
@Client.on_message(filters.command("prayer", prefix) & filters.me)
async def namaz_times(client: Client, message: Message):
if message.reply_to_message:
city_name = message.reply_to_message.text
country_name = DEFAULT_COUNTRY # Default to Pakistan if no country is provided
else:
args = message.text.split(maxsplit=2)
if len(args) < 2:
city_name = DEFAULT_CITY
country_name = DEFAULT_COUNTRY
elif len(args) == 2:
city_name = args[1]
country_name = DEFAULT_COUNTRY
else:
city_name = args[1]
country_name = args[2]
data = await fetch_namaz_times(city_name, country_name)
if "error" in data:
result = f"<b>Error:</b> <i>{data['error']}</i>"
elif "data" in data:
timings = data["data"]["timings"]
today = datetime.now().strftime("%Y-%m-%d")
formatted_timings = {
"Fajr": format_time_12hr(timings["Fajr"]),
"Dhuhr": format_time_12hr(timings["Dhuhr"]),
"Asr": format_time_12hr(timings["Asr"]),
"Maghrib": format_time_12hr(timings["Maghrib"]),
"Isha": format_time_12hr(timings["Isha"]),
}
result = (
f"<b>Prayer Times for {city_name}, {country_name} on {today}:</b>\n\n"
f"<b>Fajr:</b> {formatted_timings['Fajr']}\n"
f"<b>Dhuhr:</b> {formatted_timings['Dhuhr']}\n"
f"<b>Asr:</b> {formatted_timings['Asr']}\n"
f"<b>Maghrib:</b> {formatted_timings['Maghrib']}\n"
f"<b>Isha:</b> {formatted_timings['Isha']}\n"
)
else:
result = "<b>Error:</b> <i>Unable to get prayer times for the specified location.</i>"
await message.edit_text(result)
modules_help["namaz"] = {
"prayer [city_name] [country_name]": "Shows the prayer times. Default to Pakistan if no country is provided"
}
+534
View File
@@ -0,0 +1,534 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import os
import requests
import aiofiles
import base64
from pyrogram import Client, enums, filters
from pyrogram.types import Message, InputMediaPhoto
from pyrogram.errors import MediaCaptionTooLong, MessageTooLong
from utils.misc import prefix, modules_help
from utils.scripts import format_exc
url = "https://api.safone.co"
headers = {
"Accept-Language": "en-US,en;q=0.9",
"Connection": "keep-alive",
"DNT": "1",
"Referer": "https://api.safone.dev/docs",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"accept": "application/json",
"sec-ch-ua": '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Linux"',
}
async def make_carbon(code):
url = "https://carbonara.solopov.dev/api/cook"
async with aiohttp.ClientSession() as session:
async with session.post(url, json={"code": code}) as resp:
image_data = await resp.read()
carbon_image = Image.open(BytesIO(image_data))
enhancer = ImageEnhance.Brightness(carbon_image)
bright_image = enhancer.enhance(1.0)
output_image = BytesIO()
bright_image.save(output_image, format="PNG", quality=95)
output_image.name = "carbon.png"
return output_image
async def telegraph(title, user_name, content):
formatted_content = "<br>".join(content.split("\n"))
formatted_content = "<p>" + formatted_content + "</p>"
data = {"title": title, "content": formatted_content, "author_name": user_name}
response = requests.post(
url=f"{url}/telegraph/text", headers=headers, json=data, timeout=5
)
result = response.json()
return result["url"]
async def voice_characters():
response = requests.get(url=f"{url}/speech/characters", headers=headers, timeout=5)
result = response.json()
return ", ".join(result["characters"])
async def make_rayso(code: str, title: str, theme: str):
data = {
"code": code,
"title": title,
"theme": theme,
"padding": 64,
"language": "auto",
"darkMode": False,
}
response = requests.post(f"{url}/rayso", data=data, headers=headers)
if response.status_code != 200:
return None
result = response.json()
try:
if result["error"] is not None:
return None
except KeyError:
pass
image_data = result["image"]
file_name = "rayso.png"
with open(file_name, "wb") as f:
f.write(base64.b64decode(image_data))
return file_name
@Client.on_message(filters.command("asq", prefix) & filters.me)
async def asq(_, message: Message):
if len(message.command) > 1:
query = message.text.split(maxsplit=1)[1]
else:
await message.edit_text("Query not provided!")
return
await message.edit_text("Processing...")
response = requests.get(url=f"{url}/asq?query={query}", headers=headers, timeout=5)
if response.status_code != 200:
await message.edit_text("Something went wrong!")
return
result = response.json()
ans = result["answer"]
await message.edit_text(
f"Q. {query}\n A. {ans}", parse_mode=enums.ParseMode.MARKDOWN
)
@Client.on_message(filters.command("sgemini", prefix) & filters.me)
async def sgemini(_, message: Message):
if len(message.command) > 1:
prompt = message.text.split(maxsplit=1)[1]
else:
await message.edit_text("prompt not provided!")
return
await message.edit_text("Processing...")
response = requests.get(url=f"{url}/bard?query={prompt}", headers=headers)
if response.status_code != 200:
await message.edit_text("Something went wrong!")
return
result = response.json()
ans = result["message"]
await message.edit_text(
f"Prompt: {prompt}\n Ans: {ans}", parse_mode=enums.ParseMode.MARKDOWN
)
@Client.on_message(filters.command("app", prefix) & filters.me)
async def app(client: Client, message: Message):
try:
chat_id = message.chat.id
await message.edit_text("Processing...")
if len(message.command) > 1:
query = message.text.split(maxsplit=1)[1]
else:
message.edit_text(
"What should i search? You didn't provided me with any value to search"
)
response = requests.get(
url=f"{url}/apps?query={query}&limit=1", headers=headers, timeout=5
)
if response.status_code != 200:
await message.edit_text("Something went wrong")
return
result = response.json()
try:
coverImage_url = result["results"][0]["icon"]
coverImage = requests.get(url=coverImage_url).content
async with aiofiles.open("coverImage.jpg", mode="wb") as f:
await f.write(coverImage)
except Exception:
coverImage = None
description = result["results"][0]["description"]
developer = result["results"][0]["developer"]
IsFree = result["results"][0]["free"]
genre = result["results"][0]["genre"]
package_name = result["results"][0]["id"]
title = result["results"][0]["title"]
price = result["results"][0]["price"]
link = result["results"][0]["link"]
rating = result["results"][0]["rating"]
await message.delete()
await client.send_media_group(
chat_id,
[
InputMediaPhoto(
"coverImage.jpg",
caption=f"<b>Title:</b> <code>{title}</code>\n<b>Rating:</b> <code>{rating}</code>\n<b>IsFree:</b> <code>{IsFree}</code>\n<b>Price:</b> <code>{price}</code>\n<b>Package Name:</b> <code>{package_name}</code>\n<b>Genres:</b> <code>{genre}</code>\n<b>Developer:</b> <code>{developer}\n<b>Description:</b> {description}\n<b>Link:</b> {link}",
)
],
)
except MediaCaptionTooLong:
description = description[:850]
await message.delete()
await client.send_media_group(
chat_id,
[
InputMediaPhoto(
"coverImage.jpg",
caption=f"<b>Title:</b> <code>{title}</code>\n<b>Rating:</b> <code>{rating}</code>\n<b>IsFree:</b> <code>{IsFree}</code>\n<b>Price:</b> <code>{price}</code>\n<b>Package Name:</b> <code>{package_name}</code>\n<b>Genres:</b> <code>{genre}</code>\n<b>Developer:</b> <code>{developer}\n<b>Description:</b> {description}\n<b>Link:</b> {link}",
)
],
)
except Exception as e:
await message.edit_text(format_exc(e))
finally:
if os.path.exists("coverImage.jpg"):
os.remove("coverImage.jpg")
@Client.on_message(filters.command("tsearch", prefix) & filters.me)
async def tsearch(client: Client, message: Message):
try:
chat_id = message.chat.id
limit = 10
await message.edit_text("Processing...")
if len(message.command) > 1:
query = message.text.split(maxsplit=1)[1]
else:
message.edit_text(
"What should i search? You didn't provided me with any value to search"
)
response = requests.get(
url=f"{url}/torrent?query={query}&limit={limit}", headers=headers
)
if response.status_code != 200:
await message.edit_text("Something went wrong")
return
result = response.json()
coverImage_url = result["results"][0]["thumbnail"]
description = result["results"][0]["description"]
genre = result["results"][0]["genre"]
category = result["results"][0]["category"]
title = result["results"][0]["name"]
link = result["results"][0]["magnetLink"]
link_result = await telegraph(
title=title, user_name=message.from_user.first_name, content=link
)
language = result["results"][0]["language"]
size = result["results"][0]["size"]
results = []
for i in range(min(limit, len(result["results"]))):
descriptions = result["results"][i]["description"]
genres = result["results"][i]["genre"]
categorys = result["results"][i]["category"]
titles = result["results"][i]["name"]
links = result["results"][i]["magnetLink"]
languages = result["results"][i]["language"]
sizes = result["results"][i]["size"]
r = f"<b>Title:</b> <code>{titles}</code>\n<b>Category:</b> <code>{categorys}</code>\n<b>Language:</b> <code>{languages}</code>\n<b>Size:</b> <code>{sizes}</code>\n<b>Genres:</b> <code>{genres}</code>\n<b>Description:</b> {descriptions}\n<b>Magnet Link:</b> <code>{links}</code><br>"
results.append(r)
all_results_content = "<br>".join(results)
link_results = await telegraph(
title="Search Results",
user_name=message.from_user.first_name,
content=all_results_content,
)
if coverImage_url is not None:
coverImage = requests.get(url=coverImage_url).content
async with aiofiles.open("coverImage.jpg", mode="wb") as f:
await f.write(coverImage)
await message.delete()
await client.send_media_group(
chat_id,
[
InputMediaPhoto(
"coverImage.jpg",
caption=f"<b>Title:</b> <code>{title}</code>\n<b>Category:</b> <code>{category}</code>\n<b>Language:</b> <code>{language}</code>\n<b>Size:</b> <code>{size}</code>\n<b>Genres:</b> <code>{genre}</code>\n<b>Description:</b> {description}\n<b>Magnet Link:</b> <a href='{link_result}'>Click Here</a>\n<b>More Results:</b> <a href='{link_results}'>Click Here</a>",
)
],
)
else:
await message.edit_text(
f"<b>Title:</b> <code>{title}</code>\n<b>Category:</b> <code>{category}</code>\n<b>Language:</b> <code>{language}</code>\n<b>Size:</b> <code>{size}</code>\n<b>Genres:</b> <code>{genre}</code>\n<b>Description:</b> {description}\n<b>Magnet Link:</b> <a href='{link_result}'>Click Here</a>\n<b>More Results:</b> <a href='{link_results}'>Click Here</a>",
disable_web_page_preview=True,
)
except MediaCaptionTooLong:
description = description[:850]
await message.delete()
await client.send_media_group(
chat_id,
[
InputMediaPhoto(
"coverImage.jpg",
caption=f"<b>Title:</b> <code>{title}</code>\n<b>Category:</b> <code>{category}</code>\n<b>Language:</b> <code>{language}</code>\n<b>Size:</b> <code>{size}</code>\n<b>Genres:</b> <code>{genre}</code>\n<b>Description:</b> {description}\n<b>Magnet Link:</b> <a href='{link_result}'>Click Here</a>",
)
],
)
except MessageTooLong:
description = description[:150]
await message.edit_text(
f"<b>Title:</b> <code>{title}</code>\n<b>Category:</b> <code>{category}</code>\n<b>Language:</b> <code>{language}</code>\n<b>Size:</b> <code>{size}</code>\n<b>Genres:</b> <code>{genre}</code>\n<b>Description:</b> {description}\n<b>Magnet Link:</b> <a href='{link_result}'>Click Here</a>",
disable_web_page_preview=True,
)
except Exception as e:
await message.edit_text(format_exc(e))
finally:
if os.path.exists("coverImage.jpg"):
os.remove("coverImage.jpg")
@Client.on_message(filters.command("stts", prefix) & filters.me)
async def tts(client: Client, message: Message):
characters = await voice_characters()
await message.edit_text("<code>Please Wait...</code>")
try:
if len(message.command) > 2:
character, prompt = message.text.split(maxsplit=2)[1:]
if character not in characters:
await message.edit_text(
f"<b>Usage: </b><code>{prefix}tts [character]* [text/reply to text]*</code>\n <b>Available Characters:</b> <blockquote>{characters}</blockquote>"
)
return
elif message.reply_to_message and len(message.command) > 1:
character = message.text.split(maxsplit=1)[1]
if character in characters:
prompt = message.reply_to_message.text
else:
await message.edit_text(
f"<b>Usage: </b><code>{prefix}tts [character]* [text/reply to text]*</code>\n <b>Available Characters:</b> <blockquote>{characters}</blockquote>"
)
return
else:
await message.edit_text(
f"<b>Usage: </b><code>{prefix}tts [character]* [text/reply to text]*</code>\n <b>Available Characters:</b> <blockquote>{characters}</blockquote>"
)
return
data = {"text": prompt, "character": character}
response = requests.post(url=f"{url}/speech", headers=headers, json=data)
if response.status_code != 200:
await message.edit_text("Something went wrong")
return
result = response.json()
audio_data = result["audio"]
audio_data = base64.b64decode(audio_data)
async with aiofiles.open(f"{prompt}.mp3", mode="wb") as f:
await f.write(audio_data)
await message.delete()
await client.send_audio(
chat_id=message.chat.id,
audio=f"{prompt}.mp3",
caption=f"<b>Characters:</b> <code>{character}</code>\n<b>Prompt:</b> <code>{prompt}</code>",
)
if os.path.exists(f"{prompt}.mp3"):
os.remove(f"{prompt}.mp3")
except KeyError:
try:
error = result["error"]
await message.edit_text(error)
except KeyError:
await message.edit_text(
f"<b>Usage: </b><code>{prefix}tts [character]* [text/reply to text]*</code>\n <b>Available Characters:</b> <blockquote>{characters}</blockquote>"
)
except Exception as e:
await message.edit_text(format_exc(e))
@Client.on_message(
filters.command(["carbonnowsh", "carboon", "carbon", "cboon"], prefix) & filters.me
)
async def carbon(client: Client, message: Message):
if message.reply_to_message:
text = message.reply_to_message.text
message_id = message.reply_to_message.id
elif len(message.command) > 1:
message_id = None
text = message.text.split(maxsplit=1)[1]
else:
await message.edit_text("Query not provided!")
return
await message.edit_text("Processing...")
image_file = await make_carbon(text)
await message.delete()
try:
await client.send_photo(
chat_id=message.chat.id,
photo=image_file,
caption=f"<b>Text:</b> <code>{text}</code>",
reply_to_message_id=message_id,
)
except MediaCaptionTooLong:
cap = text[:850]
await client.send_photo(
chat_id=message.chat.id,
photo=image_file,
caption=f"<b>Text:</b> <code>{cap}</code>",
reply_to_message_id=message_id,
)
except Exception as e:
await message.edit_text(format_exc(e))
if os.path.exists("carbon.png"):
os.remove("carbon.png")
@Client.on_message(filters.command("ccgen", prefix) & filters.me)
async def ccgen(_, message: Message):
if len(message.command) > 1:
bins = message.text.split(maxsplit=1)[1]
else:
await message.edit_text("Code not provided!")
return
await message.edit_text("Processing...")
response = requests.get(url=f"{url}/ccgen?bins={bins}", headers=headers)
if response.status_code != 200:
await message.edit_text("Something went wrong")
return
result = response.json()
cards = result["results"][0]["cards"]
cards_str = "\n".join([f'"{card}"' for card in cards])
bins = result["results"][0]["bin"]
await message.edit_text(
f"Bins: <code>{bins}</code>\nTotal: <code>{len(cards)}</code>\nCards: \n<code>{cards_str}</code>"
)
@Client.on_message(filters.command("rayso", prefix) & filters.me)
async def rayso(client: Client, message: Message):
title = "Untitled"
themes = [
"vercel",
"supabase",
"tailwind",
"clerk",
"mintlify",
"prisma",
"bitmap",
"noir",
"ice",
"sand",
"forest",
"mono",
"breeze",
"candy",
"crimson",
"falcon",
"meadow",
"midnight",
"raindrop",
"sunset",
]
if message.reply_to_message:
text = message.reply_to_message.text
message_id = message.reply_to_message.id
if 2 <= len(message.command) <= 3:
title = message.text.split(maxsplit=2)[1]
theme = message.text.split(maxsplit=2)[2].lower()
if theme not in themes:
theme = "breeze"
elif len(message.command) > 1:
message_id = message.id
title = message.text.split(maxsplit=3)[1]
theme = message.text.split(maxsplit=3)[2]
if theme not in themes:
theme = "breeze"
text = message.text.split(maxsplit=3)[3]
else:
await message.edit_text("Query not provided!")
return
await message.edit_text("Processing...")
image_file = await make_rayso(text, title, theme)
if image_file is None:
await message.edit_text("Something went wrong")
return
try:
await client.send_photo(
chat_id=message.chat.id,
photo=image_file,
caption=f"<b>Text:</b> <code>{text}</code>",
reply_to_message_id=message_id,
)
await message.delete()
except MediaCaptionTooLong:
cap = text[:850]
await client.send_photo(
chat_id=message.chat.id,
photo=image_file,
caption=f"<b>Text:</b> <code>{cap}</code>",
reply_to_message_id=message_id,
)
await message.delete()
except Exception as e:
await message.edit_text(format_exc(e))
if os.path.exists(image_file):
os.remove(image_file)
modules_help["safone"] = {
"asq [query]*": "Asq",
"app [query]*": "Search for an app on Play Store",
"tsearch [query]*": "Search Torrent",
"tts [character]* [text/reply to text]*": "Convert Text to Speech",
"sgemini [prompt]*": "Gemini Model through safone api",
"carbon [code/file/reply]": "Create beautiful image with your code",
"ccgen [bins]*": "Generate credit cards",
"rayso [title]* [theme]* [text/reply to text]*": "Create beautiful image with your text",
}
+565
View File
@@ -0,0 +1,565 @@
#  Moon-Userbot - telegram userbot
#  Copyright (C) 2020-present Moon Userbot Organization
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <https://www.gnu.org/licenses/>.
import os
import requests
import asyncio
from pyrogram import Client, enums, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from modules.url import generate_screenshot
from pyrogram import filters
from utils.scripts import with_reply, no_prefix
np = no_prefix(prefix)
# API URLs
BASE_URL = "https://deliriussapi-oficial.vercel.app"
URL = f"{BASE_URL}/ia"
GOOGLE_SEARCH_URL = f"{BASE_URL}/search/googlesearch?query="
YOUTUBE_SEARCH_URL = f"{BASE_URL}/search/ytsearch?q="
MOVIE_SEARCH_URL = f"{BASE_URL}/search/movie?query="
APK_SEARCH_URL = f"https://bk9.fun/search/apkfab?q="
APK_DOWNLOAD_URL = "https://bk9.fun/download/apkfab?url="
def clean_data(data):
parts = data.split("$@$")
if len(parts) > 1:
return parts[-1]
else:
return data
# Store search results temporarily
search_results = {}
# Helper Functions
def format_google_results(results):
results = results[:15]
return results, "\n\n".join(
[
f"{i+1}. **[{item['title']}]({item['url']})**\n{item['description']}"
for i, item in enumerate(results)
]
)
def format_youtube_results(results):
results = results[:15]
return results, "\n\n".join(
[
f"{i+1}. **[{item['title']}]({item['url']})**\nPublished by: [{item['author']['name']}]({item['author']['url']}) - {item['views']} views - {item['duration']}"
for i, item in enumerate(results)
]
)
def format_movie_results(results):
results = results[:15]
return results, "\n\n".join(
[
f"{i+1}. **{item['title']}** ({item['release_date']})\nRating: {item['vote_average']}/10\nVotes: {item['vote_count']}"
for i, item in enumerate(results)
]
)
def format_apk_results(results):
results = results[:15]
return results, "\n\n".join(
[f"{i+1}. [{item['title']}]({item['link']})" for i, item in enumerate(results)]
)
async def send_screenshot(client, message, url):
screenshot_data = generate_screenshot(url)
if screenshot_data:
await client.send_photo(
message.chat.id,
screenshot_data,
caption=f"Screenshot of <code>{url}</code>",
reply_to_message_id=message.id,
)
else:
await message.reply("Failed to take screenshot.")
async def delete_search_data(client, chat_id, message_id):
await asyncio.sleep(60)
for key in ["google", "youtube", "movie", "apk"]:
search_key = f"{chat_id}_{key}"
if (
search_key in search_results
and search_results[search_key]["message_id"] == message_id
):
del search_results[search_key]
try:
await client.delete_messages(chat_id, message_id)
except:
pass
break
def format_spotify_result(data):
result = ""
for item in data[:15]: # Limit to 15 results
result += f"🎵 **{item['title']}** by {item['artist']}\n"
result += f"Album: {item['album']}\n"
result += f"Duration: {item['duration']}\n"
result += f"Popularity: {item['popularity']}\n"
result += f"Publish Date: {item['publish']}\n"
result += f"[Listen on Spotify]({item['url']})\n\n"
return result
def format_lyrics_result(data):
return f"🎵 **{data['fullTitle']}** by {data['artist']}\n\n{data['lyrics']}"
def format_soundcloud_result(data):
result = ""
for item in data[:15]: # Limit to 15 results
result += f"🎵 **{item['title']}**\n"
result += f"Genre: {item['genre']}\n"
result += f"Duration: {item['duration'] // 1000 // 60}:{item['duration'] // 1000 % 60}\n"
result += f"Likes: {item['likes']}\n"
result += f"Plays: {item['play']}\n"
result += f"[Listen on SoundCloud]({item['link']})\n\n"
return result
def format_deezer_result(data):
result = ""
for item in data[:15]: # Limit to 15 results
result += f"🎵 **{item['title']}** by {item['artist']}\n"
result += f"Duration: {item['duration']}\n"
result += f"Rank: {item['rank']}\n"
result += f"[Listen on Deezer]({item['url']})\n\n"
return result
def format_apple_music_result(data):
result = ""
for item in data[:15]: # Limit to 15 results
title = item.get("title", "Unknown Title")
artists = item.get("artists", "Unknown Artist")
music_type = item.get("type", "Unknown Type")
url = item.get("url", "#")
result += f"🎵 **{title}** by {artists}\n"
result += f"Type: {music_type}\n"
result += f"[Listen on Apple Music]({url})\n\n"
return result
async def search_music(api_url, format_function, message, query):
await message.edit("Searching...")
url = f"{api_url}{query}&limit=10"
response = requests.get(url)
if response.status_code == 200:
try:
data = response.json() # Directly get the JSON data
if isinstance(data, list):
result = format_function(data)
elif isinstance(data, dict) and "data" in data:
result = format_function(data["data"])
else:
result = "No data found or unexpected format."
await message.edit(result, parse_mode=enums.ParseMode.MARKDOWN)
except (ValueError, KeyError, TypeError) as e:
await message.edit(f"An error occurred while processing the data: {str(e)}")
elif response.json()["msg"]:
await message.edit(response.json()["msg"])
else:
await message.edit("An error occurred, please try again later.")
@Client.on_message(filters.command(["gsearch"], prefix) & filters.me)
async def google_search(client: Client, message: Message):
if message.reply_to_message:
query = message.reply_to_message.text.strip()
elif len(message.command) > 1:
query = message.text.split(maxsplit=1)[1]
else:
return await message.edit_text(f"{prefix}gsearch <query/reply to query>")
await message.edit("Searching...")
url = f"{GOOGLE_SEARCH_URL}{query}"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
results, formatted_results = format_google_results(data["data"])
search_message = await message.edit(
f"**Google Search Results for:** `{query}`\n\n{formatted_results}",
parse_mode=enums.ParseMode.MARKDOWN,
disable_web_page_preview=True,
)
search_key = f"{message.chat.id}_google"
global search_results
search_results[search_key] = {
"results": results,
"message_id": search_message.id,
}
google_url = f"https://www.google.com/search?q={query}"
await send_screenshot(client, message, google_url)
asyncio.create_task(
delete_search_data(client, message.chat.id, search_message.id)
)
else:
await message.edit("An error occurred, please try again later.")
@Client.on_message(filters.command(["ytsearch"], prefix) & filters.me)
async def youtube_search(client: Client, message: Message):
if message.reply_to_message:
query = message.reply_to_message.text.strip()
elif len(message.command) > 1:
query = message.text.split(maxsplit=1)[1]
else:
return await message.edit_text(f"{prefix}ytsearch <query/reply to query>")
await message.edit("Searching...")
url = f"{YOUTUBE_SEARCH_URL}{query}"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
results, formatted_results = format_youtube_results(data["data"])
search_message = await message.edit(
f"**YouTube Search Results for:** `{query}`\n\n{formatted_results}",
parse_mode=enums.ParseMode.MARKDOWN,
disable_web_page_preview=True,
)
search_key = f"{message.chat.id}_youtube"
global search_results
search_results[search_key] = {
"results": results,
"message_id": search_message.id,
}
youtube_url = f"https://www.youtube.com/results?search_query={query}"
await send_screenshot(client, message, youtube_url)
asyncio.create_task(
delete_search_data(client, message.chat.id, search_message.id)
)
else:
await message.edit("An error occurred, please try again later.")
@Client.on_message(filters.command(["moviesearch"], prefix) & filters.me)
async def movie_search(client, message: Message):
if message.reply_to_message:
query = message.reply_to_message.text.strip()
elif len(message.command) > 1:
query = message.text.split(maxsplit=1)[1]
else:
return await message.edit_text(f"{prefix}moviesearch <query/reply to query>")
await message.edit("Searching...")
url = f"{MOVIE_SEARCH_URL}{query}"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
results, formatted_results = format_movie_results(data["data"])
# Split the message into multiple parts if it's too long
parts = []
part_length = 4096 # Telegram's message length limit
for i in range(0, len(formatted_results), part_length):
parts.append(formatted_results[i : i + part_length])
for part in parts:
search_message = await message.reply(
f"**Movie Search Results for:** `{query}`\n\n{part}",
parse_mode=enums.ParseMode.MARKDOWN,
disable_web_page_preview=True,
)
search_key = f"{message.chat.id}_movie"
global search_results
search_results[search_key] = {
"results": results,
"message_id": search_message.id,
}
asyncio.create_task(
delete_search_data(client, message.chat.id, search_message.id)
)
else:
await message.edit("An error occurred, please try again later.")
@Client.on_message(filters.command(["apksearch"], prefix) & filters.me)
async def apk_search(client, message: Message):
if message.reply_to_message:
query = message.reply_to_message.text.strip()
elif len(message.command) > 1:
query = message.text.split(maxsplit=1)[1]
else:
return await message.edit_text(f"{prefix}apksearch <query/reply to query>")
await message.edit("Searching...")
url = f"{APK_SEARCH_URL}{query}"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
results, formatted_results = format_apk_results(data["BK9"])
search_message = await message.edit(
f"**APK Search Results for:** `{query}`\n\n{formatted_results}",
parse_mode=enums.ParseMode.MARKDOWN,
disable_web_page_preview=True,
)
search_key = f"{message.chat.id}_apk"
global search_results
search_results[search_key] = {
"results": results,
"message_id": search_message.id,
}
asyncio.create_task(
delete_search_data(client, message.chat.id, search_message.id)
)
else:
await message.edit("An error occurred, please try again later.")
@Client.on_message(filters.command(["wgpt", "gptweb"], prefix) & filters.me)
async def gptweb(_, message: Message):
if len(message.command) < 2:
await message.edit("Usage: `wgpt <query>`")
return
await message.edit("Thinking...")
query = " ".join(message.command[1:])
url = f"{URL}/gptweb?text={query}"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
await message.edit(
f"**Question:**\n{query}\n**Answer:**\n{data['data']}",
parse_mode=enums.ParseMode.MARKDOWN,
)
else:
await message.edit("An error occurred, please try again later.")
@Client.on_message(filters.command(["wgemini"], prefix) & filters.me)
async def gemini(_, message: Message):
if len(message.command) < 2:
await message.edit("Usage: `wgemini <query>`")
return
await message.edit("Thinking...")
query = " ".join(message.command[1:])
url = f"{URL}/gemini?query={query}"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
await message.edit(
f"**Question:**\n{query}\n**Answer:**\n{data['message']}",
parse_mode=enums.ParseMode.MARKDOWN,
)
else:
await message.edit("An error occurred, please try again later.")
@Client.on_message(filters.command(["sputify"], prefix) & filters.me)
async def spotify_search(_, message: Message):
query = (
message.text.split(maxsplit=1)[1]
if len(message.command) > 1
else message.reply_to_message.text
)
if not query:
await message.edit("Usage: spotify <query>")
return
await search_music(
f"{BASE_URL}/search/spotify?q=", format_spotify_result, message, query
)
@Client.on_message(filters.command(["lyrics"], prefix) & filters.me)
async def lyrics_search(_, message: Message):
query = (
message.text.split(maxsplit=1)[1]
if len(message.command) > 1
else message.reply_to_message.text
)
if not query:
await message.edit("Usage: lyrics <song name>")
return
await search_music(
f"{BASE_URL}/search/letra?query=", format_lyrics_result, message, query
)
@Client.on_message(filters.command(["soundcloud"], prefix) & filters.me)
async def soundcloud_search(_, message: Message):
query = (
message.text.split(maxsplit=1)[1]
if len(message.command) > 1
else message.reply_to_message.text
)
if not query:
await message.edit("Usage: soundcloud <query>")
return
await search_music(
f"{BASE_URL}/search/soundcloud?q=", format_soundcloud_result, message, query
)
@Client.on_message(filters.command(["deezer"], prefix) & filters.me)
async def deezer_search(_, message: Message):
query = (
message.text.split(maxsplit=1)[1]
if len(message.command) > 1
else message.reply_to_message.text
)
if not query:
await message.edit("Usage: deezer <query>")
return
await search_music(
f"{BASE_URL}/search/deezer?q=", format_deezer_result, message, query
)
@Client.on_message(filters.command(["applemusic"], prefix) & filters.me)
async def applemusic_search(_, message: Message):
query = (
message.text.split(maxsplit=1)[1]
if len(message.command) > 1
else message.reply_to_message.text
)
if not query:
await message.edit("Usage: applemusic <query>")
return
await search_music(
f"{BASE_URL}/search/applemusic?text=", format_apple_music_result, message, query
)
@Client.on_message(filters.reply & filters.text & filters.me & np)
async def handle_reply(client: Client, message: Message):
chat_id = message.chat.id
search_keys = [
f"{chat_id}_google",
f"{chat_id}_youtube",
f"{chat_id}_movie",
f"{chat_id}_apk",
]
for search_key in search_keys:
if search_key in search_results:
try:
# Check if the replied-to message is one of the bot's search result messages
if message.reply_to_message.from_user.id != (await client.get_me()).id:
return
index = int(message.text.strip()) - 1
results = search_results[search_key]["results"]
search_message_id = search_results[search_key]["message_id"]
if (
message.reply_to_message.id == search_message_id
and 0 <= index < len(results)
):
await message.edit("Please wait...")
if search_key.endswith("_movie"):
# Send movie details with image
movie = results[index]
caption = (
f"**{movie['title']}** ({movie['release_date']})\n"
f"Original Title: {movie['original_title']}\n"
f"Language: {movie['original_language']}\n"
f"Overview: {movie['overview']}\n"
f"Popularity: {movie['popularity']}\n"
f"Rating: {movie['vote_average']}/10\n"
f"Votes: {movie['vote_count']}"
)
if "image" in movie:
response = requests.get(movie["image"])
if response.status_code == 200:
with open("movie_image.jpg", "wb") as f:
f.write(response.content)
await message.reply_photo(
photo="movie_image.jpg",
caption=caption,
parse_mode=enums.ParseMode.MARKDOWN,
)
os.remove("movie_image.jpg")
else:
await message.reply(
caption, parse_mode=enums.ParseMode.MARKDOWN
)
else:
await message.reply(
caption, parse_mode=enums.ParseMode.MARKDOWN
)
elif search_key.endswith("_apk"):
apk_url = f"{APK_DOWNLOAD_URL}{results[index]['link']}"
fetch_apk_url = requests.get(apk_url)
if fetch_apk_url.status_code != 200:
await message.edit("Failed to fetch APK data.")
else:
data_apk = fetch_apk_url.json()
download_url = data_apk["BK9"]["link"]
size_apk = data_apk["BK9"]["size"]
apk_size = float(size_apk.split(" ")[0])
if "GB" in size_apk or apk_size > 100:
await message.edit(
"File size is too large to download."
)
else:
apk_file_name = f"{data_apk['BK9']['title']}.apk"
response = requests.get(download_url)
if response.status_code != 200:
await message.edit(
"Failed to download the APK file."
)
else:
with open(apk_file_name, "wb") as f:
f.write(response.content)
await message.reply_document(apk_file_name)
os.remove(apk_file_name)
else:
url = results[index]["url"]
await send_screenshot(client, message, url)
await message.delete()
return
except ValueError:
pass
modules_help["sarethai"] = {
"wgpt [query]*": "Ask anything to GPT-Web",
"gptweb [query]*": "Ask anything to GPT-Web",
"wgemini [query]*": "Ask anything to Gemini",
"sputify [query]*": "Search for songs on Spotify",
"lyrics [song name]*": "Get the lyrics of a song",
"soundcloud [query]*": "Search for songs on SoundCloud",
"deezer [query]*": "Search for songs on Deezer",
"applemusic [query]*": "Search for songs on Apple Music",
"gsearch [query]*": "Searches Google for the query.",
"ytsearch [query]*": "Searches YouTube for the query.",
"moviesearch [query]*": "Searches movies for the query and returns results.",
"apksearch [query]*": "Searches APKs for the query and returns results.",
}
+79
View File
@@ -0,0 +1,79 @@
from asyncio import sleep
from pyrogram import Client, enums, filters
from pyrogram.types import Message
# noinspection PyUnresolvedReferences
from utils.misc import modules_help, prefix
# noinspection PyUnresolvedReferences
from utils.scripts import format_exc
now = {}
@Client.on_message(filters.command(["search"], prefix) & filters.me)
async def search_cmd(client: Client, message: Message):
if now.get(message.chat.id):
return await message.edit(
"<b>You already have a search in progress!\n"
"Type: <code>{}scancel</code> to cancel it.</b>".format(prefix),
parse_mode=enums.ParseMode.HTML,
)
await message.edit("<b>Start searching...</b>", parse_mode=enums.ParseMode.HTML)
finished = False
local = False
try:
cmd = message.command[1]
word = message.command[2].lower()
timeout = float(message.command[3]) if len(message.command) > 3 else 2
except:
return await message.edit(
"<b>Usage:</b> <code>{}search [/cmd]* [search_word]* [timeout=2.0]</code>".format(
prefix
),
parse_mode=enums.ParseMode.HTML,
)
now[message.chat.id] = True
try:
await message.reply_text(quote=False, text=cmd, reply_to_message_id=None)
while not finished and now[message.chat.id]:
async for msg in client.get_chat_history(message.chat.id, limit=2):
if msg.from_user.id == message.from_user.id:
continue
elif word in msg.text.lower():
finished = True
local = True
if not local:
await sleep(timeout)
await message.reply_text(
quote=False, text=cmd, reply_to_message_id=None
)
else:
break
if now[message.chat.id]:
await message.reply_text(
"<b>Search finished!</b>", parse_mode=enums.ParseMode.HTML
)
except Exception as ex:
await message.edit(format_exc(ex), parse_mode=enums.ParseMode.HTML)
now[message.chat.id] = False
@Client.on_message(filters.command(["scancel"], prefix) & filters.me)
async def scancel_cmd(_: Client, message: Message):
if not now.get(message.chat.id):
return await message.edit(
"<b>There is no search in progress!</b>", parse_mode=enums.ParseMode.HTML
)
now[message.chat.id] = False
await message.edit("<b>Search cancelled!</b>", parse_mode=enums.ParseMode.HTML)
modules_help["search"] = {
"search [/cmd]* [search_word]* [timeout=2.0]": "Search for a specific word in bot (while)",
"scancel": "Cancel current search",
}
+64
View File
@@ -0,0 +1,64 @@
# copyright by https/t.me/shado_hackers
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.scripts import format_exc, import_library
from utils.misc import modules_help, prefix
import_library("lxml_html_clean")
import_library("newspaper", "newspaper3k")
nltk = import_library("nltk")
from newspaper import Article
from newspaper.article import ArticleException
nltk.download("all")
@Client.on_message(filters.command("summary", prefix) & filters.me)
async def summarize_article(_, message: Message):
"""
Summarize an article from a given URL.
Args:
client (Client): Pyrogram client instance.
message (Message): Incoming message.
Returns:
None
"""
# Extract the URL from the message text (removing the command part)
url = message.text.split(maxsplit=1)[1] if len(message.text.split()) > 1 else None
if not url:
await message.edit_text("Please provide a valid URL after the command.")
return
try:
# Extract and summarize the article
article = Article(url)
article.download()
article.parse()
article.nlp() # Uses NLP to analyze the article
response = f"""
<b>Article Summary</b>
<b>Title:</b> <code>{article.title}</code>
<b>Authors:</b> <code>{', '.join(article.authors) if article.authors else 'N/A'}</code>
<b>Summary:</b>
<pre>{article.summary}</pre>
"""
await message.edit_text(response)
except ArticleException:
return await message.edit_text(
"Unable to extract information from the provided URL."
)
except Exception as e:
return await message.edit_text(f"An error occurred: {format_exc(e)}")
modules_help["summary"] = {
"summary [url]": "Reply with article links, getting summary of articles"
}
+53
View File
@@ -0,0 +1,53 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from utils.misc import modules_help, prefix
ru_keys = (
"""ёйцукенгшщзхъфывапролджэячсмитьбю.Ё"№;%:?ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭ/ЯЧСМИТЬБЮ,"""
)
en_keys = (
"""`qwertyuiop[]asdfghjkl;'zxcvbnm,./~@#$%^&QWERTYUIOP{}ASDFGHJKL:"|ZXCVBNM<>?"""
)
table = str.maketrans(ru_keys + en_keys, en_keys + ru_keys)
@Client.on_message(filters.command(["switch", "sw"], prefix) & filters.me)
async def switch(client: Client, message: Message):
if len(message.command) == 1:
if message.reply_to_message:
text = message.reply_to_message.text
else:
history = await client.get_history(message.chat.id, limit=2)
if history and history[1].from_user.is_self and history[1].text:
text = history[1].text
else:
await message.edit(
"<b>Text to switch not found</b>", parse_mode=enums.ParseMode.HTML
)
return
else:
text = message.text.split(maxsplit=1)[1]
await message.edit(str.translate(text, table), parse_mode=enums.ParseMode.HTML)
modules_help["switch"] = {
"sw [reply/text for switch]*": "Useful when you forgot to change the keyboard layout[RU]",
}
+110
View File
@@ -0,0 +1,110 @@
import requests
import time
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from pyrogram.errors import MessageTooLong
import os
from utils.misc import modules_help, prefix
# Replace with your Gladia API key
gladia_key = "your key "
gladia_url = "https://api.gladia.io/v2/transcription/"
# Function to make fetch requests to the Gladia API
def make_fetch_request(url, headers, method="GET", data=None):
if method == "POST":
response = requests.post(url, headers=headers, json=data)
else:
response = requests.get(url, headers=headers)
return response.json()
@Client.on_message(filters.command("transcribeyt", prefix) & filters.me)
async def transcribe_audio(_, message: Message):
"""
Transcribe an audio URL using the Gladia API.
Usage: .transcribe <audio_url>
"""
audio_url = (
message.text.split(maxsplit=1)[1] if len(message.text.split()) > 1 else None
)
# Check if a valid URL was provided
if not audio_url:
await message.reply("Please provide a valid audio URL.")
return
headers = {"x-gladia-key": gladia_key, "Content-Type": "application/json"}
request_data = {"audio_url": audio_url}
# Send initial request to Gladia API
status_message = await message.reply("- Sending initial request to Gladia API...")
initial_response = make_fetch_request(gladia_url, headers, "POST", request_data)
# Check if the response contains the result_url
if "result_url" not in initial_response:
await status_message.edit(f"Error in transcription request: {initial_response}")
return
result_url = initial_response["result_url"]
await status_message.edit(
f"Initial request sent. Polling for transcription results..."
)
# Polling for transcription result
while True:
poll_response = make_fetch_request(result_url, headers)
if poll_response.get("status") == "done":
transcription = (
poll_response.get("result", {})
.get("transcription", {})
.get("full_transcript")
)
if transcription:
# Format the transcription result with HTML
result_html = f"""
<u><b>Transcription Result</b></u>
<br>
<pre>{transcription}</pre>
"""
try:
# Attempt to send transcription as a message
await message.reply_text(
result_html, parse_mode=enums.ParseMode.HTML
)
except MessageTooLong:
# Save the large response to a file
with open("transcription.txt", "w") as f:
f.write(result_html)
# Read general details to include in the caption
general_details = "Here's the transcription result."
# Send the file with a caption
await message.reply_document(
"transcription.txt",
caption=f"<u><b>General Details</b></u>:\n{general_details}",
)
# Clean up by removing the file
os.remove("transcription.html")
else:
await status_message.edit(
"Transcription completed, but no transcript was found."
)
break
else:
await status_message.edit(
f"Transcription status: {poll_response.get('status')}"
)
time.sleep(30) # Wait for a few seconds before polling again
modules_help["transcribeyt"] = {
"transcribeyt [yt video url]": "Reply with a YT video link to get transcribed "
}
+143
View File
@@ -0,0 +1,143 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, errors, filters
from pyrogram.types import Message
from utils.db import db
from utils.handlers import NoteSendHandler
from utils.misc import modules_help, prefix
@Client.on_message(filters.command(["save"], prefix) & filters.me)
async def save_note(client: Client, message: Message):
await message.edit("<b>Loading...</b>")
try:
chat = await client.get_chat(db.get("core.notes", "chat_id", 0))
except (errors.RPCError, ValueError, KeyError):
# group is not accessible or isn't created
chat = await client.create_supergroup(
"Userbot_Notes_Filters", "Don't touch this group, please"
)
db.set("core.notes", "chat_id", chat.id)
chat_id = chat.id
if message.reply_to_message and len(message.text.split()) >= 2:
note_name = message.text.split(maxsplit=1)[1]
if message.reply_to_message.media_group_id:
checking_note = db.get("core.notes", f"note{note_name}", False)
if not checking_note:
get_media_group = [
_.id
for _ in await client.get_media_group(
message.chat.id, message.reply_to_message.id
)
]
try:
message_id = await client.forward_messages(
chat_id, message.chat.id, get_media_group
)
except errors.ChatForwardsRestricted:
await message.edit(
"<b>Forwarding messages is restricted by chat admins</b>",
)
return
note = {
"MESSAGE_ID": str(message_id[1].id),
"MEDIA_GROUP": True,
"CHAT_ID": str(chat_id),
}
db.set("core.notes", f"note{note_name}", note)
await message.edit(f"<b>Note {note_name} saved</b>")
else:
await message.edit("<b>This note already exists</b>")
else:
checking_note = db.get("core.notes", f"note{note_name}", False)
if not checking_note:
try:
message_id = await message.reply_to_message.forward(chat_id)
except errors.ChatForwardsRestricted:
message_id = await message.copy(chat_id)
note = {
"MEDIA_GROUP": False,
"MESSAGE_ID": str(message_id.id),
"CHAT_ID": str(chat_id),
}
db.set("core.notes", f"note{note_name}", note)
await message.edit(f"<b>Note {note_name} saved</b>")
else:
await message.edit("<b>This note already exists</b>")
elif len(message.text.split()) >= 3:
note_name = message.text.split(maxsplit=1)[1].split()[0]
checking_note = db.get("core.notes", f"note{note_name}", False)
if not checking_note:
message_id = await client.send_message(
chat_id, message.text.split(note_name)[1].strip()
)
note = {
"MEDIA_GROUP": False,
"MESSAGE_ID": str(message_id.id),
"CHAT_ID": str(chat_id),
}
db.set("core.notes", f"note{note_name}", note)
await message.edit(f"<b>Note {note_name} saved</b>")
else:
await message.edit("<b>This note already exists</b>")
else:
await message.edit(
f"<b>Example: <code>{prefix}save note_name</code></b>",
)
@Client.on_message(filters.command("note", prefix) & filters.me)
async def note_send(client: Client, message: Message):
handler = NoteSendHandler(client, message)
await handler.handle_note_send()
@Client.on_message(filters.command(["notes"], prefix) & filters.me)
async def notes(_, message: Message):
await message.edit("<b>Loading...</b>")
text = "Available notes:\n\n"
collection = db.get_collection("core.notes")
for note in collection.keys():
if note[:4] == "note":
text += f"<code>{note[4:]}</code>\n"
await message.edit(text)
@Client.on_message(filters.command(["clear"], prefix) & filters.me)
async def clear_note(_, message: Message):
if len(message.text.split()) >= 2:
note_name = message.text.split(maxsplit=1)[1]
find_note = db.get("core.notes", f"note{note_name}", False)
if find_note:
db.remove("core.notes", f"note{note_name}")
await message.edit(f"<b>Note {note_name} deleted</b>")
else:
await message.edit("<b>There is no such note</b>")
else:
await message.edit(f"<b>Example: <code>{prefix}clear note_name</code></b>")
modules_help["notes"] = {
"save [name]*": "Save note",
"note [name]*": "Get saved note",
"notes": "Get note list",
"clear [name]*": "Delete note",
}
+126
View File
@@ -0,0 +1,126 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import datetime
import os
import time
import aiofiles
from pyrogram import Client, filters
from pyrogram.errors import MessageTooLong
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import edit_or_reply, format_exc, progress
from utils.rentry import paste as rentry_paste
async def read_file(file_path):
async with aiofiles.open(file_path, mode="r") as file:
content = await file.read()
return content
def check_extension(file_path):
extensions = {
".txt": "<pre lang='plaintext'>",
".py": "<pre lang='python'>",
".js": "<pre lang='javascript'>",
".json": "<pre lang='json'>",
".smali": "<pre lang='smali'>",
".sh": "<pre lang='shell'>",
".c": "<pre lang='c'>",
".java": "<pre lang='java'>",
".php": "<pre lang='php'>",
".doc": "<pre lang='doc'>",
".docx": "<pre lang='docx'>",
".rtf": "<pre lang='rtf'>",
".s": "<pre lang='asm'>",
".dart": "<pre lang='dart'>",
".cfg": "<pre lang='cfg'>",
".swift": "<pre lang='swift'>",
".cs": "<pre lang='csharp'>",
".vb": "<pre lang='vb'>",
".css": "<pre lang='css'>",
".htm": "<pre lang='html'>",
".html": "<pre lang='html'>",
".rss": "<pre lang='xml'>",
".xhtml": "<pre lang='xtml'>",
".cpp": "<pre lang='cpp'>",
}
ext = os.path.splitext(file_path)[1].lower()
return extensions.get(ext, "<pre>")
@Client.on_message(filters.command("open", prefix) & filters.me)
async def openfile(client: Client, message: Message):
if not message.reply_to_message:
return await message.edit_text("Kindly Reply to a File")
try:
ms = await edit_or_reply(message, "<b>Downloading...</b>")
ct = time.time()
file_path = await message.reply_to_message.download(
progress=progress, progress_args=(ms, ct, "Downloading...")
)
await ms.edit_text("<code>Trying to open file...</code>")
file_info = os.stat(file_path)
file_name = file_path.split("/")[-1:]
file_size = file_info.st_size
last_modified = datetime.datetime.fromtimestamp(file_info.st_mtime).strftime(
"%Y-%m-%d %H:%M:%S"
)
code_start = check_extension(file_path=file_path)
content = await read_file(file_path=file_path)
await ms.edit_text(
f"<b>File Name:</b> <code>{file_name[0]}</code>\n<b>Size:</b> <code>{file_size} bytes</code>\n<b>Last Modified:</b> <code>{last_modified}</code>\n<b>Content:</b> {code_start}{content}</pre>",
)
except MessageTooLong:
await ms.edit_text(
"<code>File Content is too long... Pasting to rentry...</code>"
)
content_new = f"```{code_start[11:-2]}\n{content}```"
try:
rentry_url, edit_code = await rentry_paste(
text=content_new, return_edit=True
)
except RuntimeError:
await ms.edit_text("<b>Error:</b> <code>Failed to paste to rentry</code>")
return
await client.send_message(
"me",
f"Here's your edit code for Url: {rentry_url}\nEdit code: <code>{edit_code}</code>",
disable_web_page_preview=True,
)
await ms.edit_text(
f"<b>File Name:</b> <code>{file_name[0]}</code>\n<b>Size:</b> <code>{file_size} bytes</code>\n<b>Last Modified:</b> <code>{last_modified}</code>\n<b>Content:</b> {rentry_url}\n<b>Note:</b> <code>Edit Code has been sent to your saved messages</code>",
disable_web_page_preview=True,
)
except Exception as e:
await ms.edit_text(format_exc(e))
finally:
if os.path.exists(file_path):
os.remove(file_path)
modules_help["open"] = {
"open": "Open content of any text supported filetype and show it's raw data"
}
+88
View File
@@ -0,0 +1,88 @@
import os
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import import_library
from utils.config import gemini_key
import_library("pyzerox", "py-zerox")
from pyzerox import zerox
from pyzerox.errors import ModelAccessError, NotAVisionModel
import litellm
kwargs = {}
CUSTOM_SYSTEM_PROMPT = "For the below pdf page, convert it into as accurate markdown format as possible with it's structure intact i.e, tables, charts, layouts etc. Return only the markdown with no explanation text. Do not exclude any content from the page."
MODEL = "gemini/gemini-1.5-pro"
@Client.on_message(filters.command("pdf2md", prefix) & filters.me)
async def pdf2md(client: Client, message: Message):
if not message.reply_to_message:
await message.edit("Reply to a pdf file")
return
if not message.reply_to_message.document:
await message.edit("Reply to a pdf file")
return
if not message.reply_to_message.document.mime_type == "application/pdf":
await message.edit("Reply to a pdf file")
return
if gemini_key == "":
await message.edit("Set GEMINI_KEY to use this command")
return
file_name = message.reply_to_message.document.file_name
file_name = file_name.split(".")[0]
if os.path.exists(f"{file_name}.md"):
os.remove(f"{file_name}.md")
md = f"{file_name}.md"
os.environ["GEMINI_API_KEY"] = gemini_key
await message.edit("Downloading pdf...")
pdf = await message.reply_to_message.download()
await message.edit("Converting pdf to markdown...")
try:
result = await zerox(
file_path=pdf,
model=MODEL,
custom_system_prompt=CUSTOM_SYSTEM_PROMPT,
select_pages=None,
**kwargs,
)
if result:
pages = result.pages
for page in pages:
with open(md, "a") as f:
f.write(page.content)
f.write("\n\n")
else:
await message.edit("No result")
return
except ModelAccessError:
await message.edit("Model not accessible")
return
except NotAVisionModel:
await message.edit("Model is not a vision model")
return
except litellm.InternalServerError:
await message.edit("Internal Server Error")
return
except Exception as e:
await message.edit(f"Error: {e}")
return
await message.edit("Uploading markdown...")
await client.send_document(
message.chat.id,
document=md,
file_name=f"{message.reply_to_message.document.file_name.split('.')[0]}.md",
reply_to_message_id=message.reply_to_message.id,
)
await message.delete()
os.remove(pdf)
os.remove(md)
modules_help["pdf2md"] = {"pdf2md": "Convert a pdf to markdown"}
+37
View File
@@ -0,0 +1,37 @@
from pyrogram import Client, filters, enums
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import with_reply
import random
@Client.on_message(filters.command("prus", prefix) & filters.me)
@with_reply
async def prussian_cmd(_, message: Message):
words = [
"сука",
"нахуй",
"блять",
"блядь",
"пиздец",
"еблан",
"уебан",
"уебок",
"пизда",
"очко",
"хуй",
]
splitted = message.reply_to_message.text.split()
for i in range(0, len(splitted), random.randint(2, 3)):
for j in range(1, 2):
splitted.insert(i, random.choice(words))
await message.edit(" ".join(splitted), parse_mode=enums.ParseMode.HTML)
modules_help["perfectrussian"] = {
"prus": "translate your message into perfect 🇷🇺Russian",
}
+32
View File
@@ -0,0 +1,32 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
@Client.on_message(filters.command(["ping", "p"], prefix) & filters.me)
async def ping(client: Client, message: Message):
latency = await client.ping()
await message.edit(f"<b>Pong! {latency}ms</b>")
modules_help["ping"] = {
"ping": "Check ping to Telegram servers",
}
+52
View File
@@ -0,0 +1,52 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.db import db
from utils.misc import modules_help, prefix
from utils.scripts import restart
@Client.on_message(
filters.command(["sp", "setprefix"], prefix) & filters.me
)
async def setprefix(_, message: Message):
if len(message.command) > 1:
pref = message.command[1]
db.set("core.main", "prefix", pref)
await message.edit(
f"<b>Prefix [ <code>{pref}</code> ] is set!\nRestarting...</b>"
)
db.set(
"core.updater",
"restart_info",
{
"type": "restart",
"chat_id": message.chat.id,
"message_id": message.id,
},
)
restart()
else:
await message.edit("<b>The prefix must not be empty!</b>")
modules_help["prefix"] = {
"sp [prefix]": "Set custom prefix",
"setprefix [prefix]": "Set custom prefix",
}
+54
View File
@@ -0,0 +1,54 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import asyncio
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import with_reply
@Client.on_message(filters.command("del", prefix) & filters.me)
async def del_msg(_, message: Message):
await message.delete()
await message.reply_to_message.delete()
@Client.on_message(filters.command("purge", prefix) & filters.me)
@with_reply
async def purge(client: Client, message: Message):
chunk = []
async for msg in client.get_chat_history(
chat_id=message.chat.id,
limit=message.id - message.reply_to_message.id + 1,
):
if msg.id < message.reply_to_message.id:
break
chunk.append(msg.id)
if len(chunk) >= 100:
await client.delete_messages(message.chat.id, chunk)
chunk.clear()
await asyncio.sleep(1)
if len(chunk) > 0:
await client.delete_messages(message.chat.id, chunk)
modules_help["purge"] = {
"purge [reply]": "Purge (delete all messages) chat from replied message to last",
"del [reply]": "Delete replied message",
}
+86
View File
@@ -0,0 +1,86 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from contextlib import redirect_stdout
from io import StringIO
from pyrogram import Client, filters
from pyrogram.types import Message
# noinspection PyUnresolvedReferences
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
# noinspection PyUnresolvedReferences
# noinspection PyUnusedLocal
@Client.on_message(
filters.command(["ex", "exec", "py", "exnoedit"], prefix) & filters.me
)
async def user_exec(_: Client, message: Message):
if len(message.command) == 1:
await message.edit("<b>Code to execute isn't provided</b>")
return
code = message.text.split(maxsplit=1)[1]
stdout = StringIO()
await message.edit("<b>Executing...</b>")
try:
with redirect_stdout(stdout):
exec(code) # skipcq
text = (
"<b>Code:</b>\n"
f"<code>{code}</code>\n\n"
"<b>Result</b>:\n"
f"<code>{stdout.getvalue()}</code>"
)
if message.command[0] == "exnoedit":
await message.reply(text)
else:
await message.edit(text)
except Exception as e:
await message.edit(format_exc(e))
# noinspection PyUnusedLocal
@Client.on_message(filters.command(["ev", "eval"], prefix) & filters.me)
async def user_eval(client: Client, message: Message):
if len(message.command) == 1:
await message.edit("<b>Code to eval isn't provided</b>")
return
code = message.text.split(maxsplit=1)[1]
try:
result = eval(code) # skipcq
await message.edit(
"<b>Expression:</b>\n"
f"<code>{code}</code>\n\n"
"<b>Result</b>:\n"
f"<code>{result}</code>"
)
except Exception as e:
await message.edit(format_exc(e))
modules_help["python"] = {
"ex [python code]": "Execute Python code",
"exnoedit [python code]": "Execute Python code and return result with reply",
"eval [python code]": "Eval Python code",
}
+44
View File
@@ -0,0 +1,44 @@
import asyncio, random
from pyrogram import Client, filters, enums
from pyrogram.raw import functions
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
emojis = [
"👍",
"👎",
"❤️",
"🔥",
"🥰",
"👏",
"😁",
"🤔",
"🤯",
"😱",
"🤬",
"😢",
"🎉",
"🤩",
"🤮",
"💩",
]
@Client.on_message(filters.command("reactspam", prefix) & filters.me)
async def reactspam(client: Client, message: Message):
await message.edit(f"<b>One moment...</b>", parse_mode=enums.ParseMode.HTML)
try:
selected_emojis = random.sample(emojis, 3)
print(selected_emojis)
await client.send_reaction(
message.chat.id,
message_id=message.reply_to_message.id,
emoji=selected_emojis,
)
await message.delete()
except Exception as e:
return await message.edit_text(format_exc(e))
modules_help["reactionspam"] = {"reactspam [amount]* [emoji]*": "spam reactions"}
+194
View File
@@ -0,0 +1,194 @@
# Copyright (C) 2020-2021 by DevsExpo@Github, < https://github.com/DevsExpo >.
#
# This file is part of < https://github.com/DevsExpo/FridayUserBot > project,
# and is released under the "GNU v3.0 License Agreement".
# Please see < https://github.com/DevsExpo/blob/master/LICENSE >
#
# All rights reserved.
# Modifed by @moonuserbot
import io
import os
from datetime import datetime
from functools import wraps
from io import BytesIO
import requests
from PIL import Image
from pyrogram import Client, enums, filters
from pyrogram.types import Message
from utils.config import rmbg_key
from utils.misc import modules_help, prefix
from utils.scripts import edit_or_reply, format_exc
async def convert_to_image(message, client) -> None | str:
"""Convert Most Media Formats To Raw Image"""
if not message:
return None
if not message.reply_to_message:
return None
final_path = None
if not (
message.reply_to_message.video
or message.reply_to_message.photo
or message.reply_to_message.sticker
or message.reply_to_message.media
or message.reply_to_message.animation
or message.reply_to_message.audio
or message.reply_to_message.document
):
return None
if message.reply_to_message.photo:
final_path = await message.reply_to_message.download()
elif message.reply_to_message.sticker:
if message.reply_to_message.sticker.mime_type == "image/webp":
final_path = "webp_to_png_s_proton.png"
path_s = await message.reply_to_message.download()
im = Image.open(path_s)
im.save(final_path, "PNG")
else:
path_s = await client.download_media(message.reply_to_message)
final_path = "lottie_proton.png"
cmd = (
f"lottie_convert.py --frame 0 -if lottie -of png {path_s} {final_path}"
)
await exec(cmd) # skipcq
elif message.reply_to_message.audio:
thumb = message.reply_to_message.audio.thumbs[0].file_id
final_path = await client.download_media(thumb)
elif message.reply_to_message.video or message.reply_to_message.animation:
final_path = "fetched_thumb.png"
vid_path = await client.download_media(message.reply_to_message)
await exec(
f"ffmpeg -i {vid_path} -filter:v scale=500:500 -an {final_path}"
) # skipcq
elif message.reply_to_message.document:
if message.reply_to_message.document.mime_type == "image/jpeg":
final_path = await message.reply_to_message.download()
elif message.reply_to_message.document.mime_type == "image/png":
final_path = await message.reply_to_message.download()
elif message.reply_to_message.document.mime_type == "image/webp":
final_path = "webp_to_png_s_proton.png"
path_s = await message.reply_to_message.download()
im = Image.open(path_s)
im.save(final_path, "PNG")
else:
return None
return final_path
def remove_background(photo_data):
with open(photo_data, "rb") as image_file:
image_data = image_file.read()
response = requests.post(
"https://api.remove.bg/v1.0/removebg",
files={"image_file": image_data},
data={"size": "auto"},
headers={"X-Api-Key": rmbg_key},
)
if response.status_code == 200:
return BytesIO(response.content)
print("Error:", response.status_code, response.text)
return None
def _check_rmbg(func):
@wraps(func)
async def check_rmbg(client: Client, message: Message):
if not rmbg_key:
await edit_or_reply(
message,
"<code>Is Your RMBG Api 'rmbg_key' Valid Or You Didn't Add It??</code>",
)
else:
await func(client, message)
return check_rmbg
@Client.on_message(filters.command("rmbg", prefix) & filters.me)
@_check_rmbg
async def rmbg(client: Client, message: Message):
pablo = await edit_or_reply(message, "<code>Processing...</code>")
if not message.reply_to_message:
await pablo.edit("<code>Reply To A Image Please!</code>")
return
cool = await convert_to_image(message, client)
if not cool:
await pablo.edit("<code>Reply to a valid media first.</code>")
return
start = datetime.now()
await pablo.edit("sending to ReMove.BG")
input_file_name = cool
files = {
"image_file": (input_file_name, open(input_file_name, "rb")),
}
r = requests.post(
"https://api.remove.bg/v1.0/removebg",
headers={"X-Api-Key": rmbg_key},
files=files,
allow_redirects=True,
stream=True,
)
if os.path.exists(cool):
os.remove(cool)
output_file_name = r
contentType = output_file_name.headers.get("content-type")
if "image" in contentType:
with io.BytesIO(output_file_name.content) as remove_bg_image:
remove_bg_image.name = "BG_rem.png"
await client.send_document(
message.chat.id, remove_bg_image, reply_to_message_id=message.id
)
end = datetime.now()
ms = (end - start).seconds
await pablo.edit(
f"<code>Removed image's Background in {ms} seconds."
)
if os.path.exists("BG_rem.png"):
os.remove("BG_rem.png")
else:
await pablo.edit(
"ReMove.BG API returned Errors."
+ f"\n`{output_file_name.content.decode('UTF-8')}"
)
@Client.on_message(filters.command("rebg", prefix) & filters.me)
async def rembg(client: Client, message: Message):
await message.edit("<code>Processing...</code>")
chat_id = message.chat.id
try:
try:
photo_data = await message.download()
except ValueError:
try:
photo_data = await message.reply_to_message.download()
except ValueError:
await message.edit("<b>File not found</b>")
return
background_removed_data = remove_background(photo_data)
if background_removed_data:
await message.delete()
await client.send_photo(
chat_id, photo=background_removed_data, caption="Background removed!"
)
else:
await message.edit_text(
"`Is Your RMBG Api 'rmbg_key' Valid Or You Didn't Add It??`\n **Check logs for details**",
parse_mode=enums.ParseMode.MARKDOWN,
)
except Exception as e:
await message.reply_text(f"An error occurred: {format_exc(e)}")
finally:
if os.path.exists(photo_data):
os.remove(photo_data)
modules_help["removebg"] = {
"rebg [reply to image]*": "remove background from image without transparency",
"rmbg [reply to image]*": "remove background from image with transparency",
}
+37
View File
@@ -0,0 +1,37 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
@Client.on_message(filters.command(["say", "s"], prefix) & filters.me)
async def say(_, message: Message):
if len(message.command) == 1:
return
command = " ".join(message.command[1:])
await message.edit(f"<code>{command}</code>")
modules_help["say"] = {
"say [command]*": "Send message that won't be interpreted by userbot",
}
+58
View File
@@ -0,0 +1,58 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import os
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_exc, format_module_help, format_small_module_help
@Client.on_message(filters.command(["sendmod", "sm"], prefix) & filters.me)
async def sendmod(client: Client, message: Message):
if len(message.command) == 1:
await message.edit("<b>Module name to send is not provided</b>")
return
await message.edit("<b>Dispatching...</b>")
try:
module_name = message.command[1].lower()
if module_name in modules_help:
text = format_module_help(module_name)
if len(text) >= 1024:
text = format_small_module_help(module_name)
if os.path.isfile(f"modules/{module_name}.py"):
await client.send_document(
message.chat.id, f"modules/{module_name}.py", caption=text
)
elif os.path.isfile(f"modules/custom_modules/{module_name.lower()}.py"):
await client.send_document(
message.chat.id,
f"modules/custom_modules/{module_name}.py",
caption=text,
)
await message.delete()
else:
await message.edit(f"<b>Module {module_name} not found!</b>")
except Exception as e:
await message.edit(format_exc(e))
modules_help["sendmod"] = {
"sendmod [module_name]": "Send module to interlocutor",
}
+156
View File
@@ -0,0 +1,156 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# TODO: Add ability to kill session by hash
import time
from datetime import datetime
from html import escape
from pyrogram import Client, filters
from pyrogram import ContinuePropagation
from pyrogram.errors import RPCError
from pyrogram.raw.functions.account import GetAuthorizations, ResetAuthorization
from pyrogram.raw.types import UpdateServiceNotification
from pyrogram.types import Message
from utils.db import db
from utils.misc import modules_help, prefix
auth_hashes = db.get("core.sessionkiller", "auths_hashes", [])
@Client.on_message(filters.command(["sessions"], prefix) & filters.me)
async def sessions_list(client: Client, message: Message):
formatted_sessions = []
sessions = (await client.invoke(GetAuthorizations())).authorizations
for num, session in enumerate(sessions, 1):
formatted_sessions.append(
f"<b>{num}</b>. <b>{escape(session.device_model)}</b> on <code>{escape(session.platform if session.platform != '' else 'unknown platform')}</code>\n"
f"<b>Hash:</b> <code>{session.hash}</code>\n"
f"<b>App name:</b> <code>{escape(session.app_name)}</code> <code>v.{escape(session.app_version if session.app_version != '' else 'unknown')}</code>\n"
f"<b>Created (last activity):</b> {datetime.fromtimestamp(session.date_created).isoformat()} ({datetime.fromtimestamp(session.date_active).isoformat()})\n"
f"<b>IP and location: </b>: <code>{session.ip}</code> (<i>{session.country}</i>)\n"
f"<b>Official status:</b> <code>{'' if session.official_app else '❌️'}</code>\n"
f"<b>2FA accepted:</b> <code>{'❌️' if session.password_pending else ''}</code>\n"
f"<b>Can accept calls / secret chats:</b> {'❌️' if session.call_requests_disabled else ''} / {'❌️' if session.encrypted_requests_disabled else ''}"
)
answer = "<b>Active sessions at your account:</b>\n\n"
chunk = []
for s in formatted_sessions:
chunk.append(s)
if len(chunk) == 5:
answer += "\n\n".join(chunk)
await message.reply(answer)
answer = ""
chunk.clear()
if chunk:
await message.reply("\n\n".join(chunk))
await message.delete()
@Client.on_message(filters.command(["sessionkiller", "sk"], prefix) & filters.me)
async def sessionkiller(client: Client, message: Message):
if len(message.command) == 1:
if db.get("core.sessionkiller", "enabled", False):
await message.edit(
"<b>Sessionkiller status: enabled\n"
f"You can disable it with <code>{prefix}sessionkiller disable</code></b>"
)
else:
await message.edit(
"<b>Sessionkiller status: disabled\n"
f"You can enable it with <code>{prefix}sessionkiller enable</code></b>"
)
elif message.command[1] in ["enable", "on", "1", "yes", "true"]:
db.set("core.sessionkiller", "enabled", True)
await message.edit("<b>Sessionkiller enabled!</b>")
db.set(
"core.sessionkiller",
"auths_hashes",
[
auth.hash
for auth in (await client.invoke(GetAuthorizations())).authorizations
],
)
elif message.command[1] in ["disable", "off", "0", "no", "false"]:
db.set("core.sessionkiller", "enabled", False)
await message.edit("<b>Sessionkiller disabled!</b>")
else:
await message.edit(f"<b>Usage: {prefix}sessionkiller [enable|disable]</b>")
@Client.on_raw_update()
async def check_new_login(client: Client, update: UpdateServiceNotification, _, __):
if not isinstance(update, UpdateServiceNotification) or not update.type.startswith(
"auth"
):
raise ContinuePropagation
if not db.get("core.sessionkiller", "enabled", False):
raise ContinuePropagation
authorizations = (await client.invoke(GetAuthorizations()))["authorizations"]
for auth in authorizations:
if auth.current:
continue
if auth["hash"] not in auth_hashes:
# found new unexpected login
try:
await client.invoke(ResetAuthorization(hash=auth.hash))
except RPCError:
info_text = (
"Someone tried to log in to your account. You can see this report because you"
"turned on this feature. But I couldn't terminate attacker's session and "
"⚠ <b>you must reset it manually</b>. You should change your 2FA password "
"(if enabled), or set it.\n"
)
else:
info_text = (
"Someone tried to log in to your account. Since you have enabled "
"this feature, I deleted the attacker's session from your account. "
"You should change your 2FA password (if enabled), or set it.\n"
)
logined_time = datetime.utcfromtimestamp(auth.date_created).strftime(
"%d-%m-%Y %H-%M-%S UTC"
)
full_report = (
"<b>!!! ACTION REQUIRED !!!</b>\n"
+ info_text
+ "Below is the information about the attacker that I got.\n\n"
f"Unique authorization hash: <code>{auth.hash}</code> (not valid anymore)\n"
f"Device model: <code>{escape(auth.device_model)}</code>\n"
f"Platform: <code>{escape(auth.platform)}</code>\n"
f"API ID: <code>{auth.api_id}</code>\n"
f"App name: <code>{escape(auth.app_name)}</code>\n"
f"App version: <code>{auth.app_version}</code>\n"
f"Logined at: <code>{logined_time}</code>\n"
f"IP: <code>{auth.ip}</code>\n"
f"Country: <code>{auth.country}</code>\n"
f"Official app: <b>{'yes' if auth.official_app else 'no'}</b>\n\n"
f"<b>It is you? Type <code>{prefix}sk off</code> and try logging "
f"in again.</b>"
)
# schedule sending report message so user will get notification
schedule_date = int(time.time() + 15)
await client.send_message("me", full_report, schedule_date=schedule_date)
return
modules_help["sessions"] = {
"sessionkiller [enable|disable]": "When enabled, every new session will be terminated.\n"
"Useful for additional protection for your account",
"sessions": "List all sessions on your account",
}
+52
View File
@@ -0,0 +1,52 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.errors import YouBlockedUser
from pyrogram.types import Message
from utils.conv import Conversation
from utils.misc import modules_help, prefix
from utils.scripts import format_exc
@Client.on_message(filters.command("sgb", prefix) & filters.me)
async def sg(client: Client, message: Message):
if message.reply_to_message and message.reply_to_message.from_user:
user_id = message.reply_to_message.from_user.id
else:
await message.edit(f"<b>Usage: </b><code>{prefix}sgb [id]</code>")
return
try:
await message.edit("<code>Processing please wait</code>")
bot_username = "@SangMata_beta_bot"
async with Conversation(client, bot_username, timeout=15) as conv:
await conv.send_message(str(user_id))
response = await conv.get_response(timeout=10)
if "you have used up your quota" in response.text:
await message.edit(response.text.splitlines()[0])
return
return await message.edit(response.text)
except YouBlockedUser:
await message.edit("<i>Please unblock @SangMata_beta_bot first.</i>")
except TimeoutError:
await message.edit("<i>No response from bot within the timeout period.</i>")
except Exception as e:
await message.edit(f"<i>Error: {format_exc(e)}</i>")
modules_help["sangmata"] = {"sgb": "reply to any user"}
+64
View File
@@ -0,0 +1,64 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from subprocess import Popen, PIPE, TimeoutExpired
import os
from time import perf_counter
from pyrogram import Client, filters
from pyrogram.types import Message
from pyrogram.errors import MessageTooLong
from utils.misc import modules_help, prefix
@Client.on_message(filters.command(["shell", "sh"], prefix) & filters.me)
async def shell(_, message: Message):
if len(message.command) < 2:
return await message.edit("<b>Specify the command in message text</b>")
cmd_text = message.text.split(maxsplit=1)[1]
cmd_args = cmd_text.split()
cmd_obj = Popen(
cmd_args,
stdout=PIPE,
stderr=PIPE,
text=True,
)
char = "#" if os.getuid() == 0 else "$"
text = f"<b>{char}</b> <code>{cmd_text}</code>\n\n"
await message.edit(text + "<b>Running...</b>")
try:
start_time = perf_counter()
stdout, stderr = cmd_obj.communicate(timeout=60)
except TimeoutExpired:
text += "<b>Timeout expired (60 seconds)</b>"
else:
stop_time = perf_counter()
if stdout:
text += f"<b>Output:</b>\n<code>{stdout}</code>\n\n"
if stderr:
text += f"<b>Error:</b>\n<code>{stderr}</code>\n\n"
text += f"<b>Completed in {round(stop_time - start_time, 5)} seconds with code {cmd_obj.returncode}</b>"
try:
await message.edit(text)
except MessageTooLong:
await message.edit(text[:-100])
cmd_obj.kill()
modules_help["shell"] = {"sh [command]*": "Execute command in shell"}
+200
View File
@@ -0,0 +1,200 @@
from datetime import datetime
import json
import requests
from pyrogram import Client, enums, filters
from pyrogram.types import Message
import io
from utils.misc import modules_help, prefix
TIKTOK_API_URL = "https://api.maher-zubair.tech/stalk/tiktok?q="
INSTAGRAM_API_URL = "https://tools.betabotz.eu.org/tools/stalk-ig?q="
GH_STALK = "https://api.github.com/users/"
@Client.on_message(filters.command(["tiktokstalk"], prefix) & filters.me)
async def tiktok_stalk(_, message: Message):
query = ""
if len(message.command) > 1:
query = message.command[1]
elif message.reply_to_message:
query = message.reply_to_message.text.strip()
if not query:
await message.edit(
"Usage: `tiktokstalk <username>` or reply to a message containing the username."
)
return
await message.edit("Fetching TikTok profile...")
url = f"{TIKTOK_API_URL}{query}"
response = requests.get(url)
if response.status_code == 200:
data = response.json().get("result", {})
if data:
profile_pic_url = data.get("profile", "")
profile_pic = requests.get(profile_pic_url).content
profile_pic_stream = io.BytesIO(profile_pic)
profile_pic_stream.name = "profile.jpg"
await message.reply_photo(
photo=profile_pic_stream,
caption=(
f"</b>TikTok Profile:</b>\n"
f"</b>Name:</b> {data.get('name', 'N/A')}\n"
f"</b>Username:</b> {data.get('username', 'N/A')}\n"
f"</b>Followers:</b> {data.get('followers', 'N/A')}\n"
f"</b>Following:</b> {data.get('following', 'N/A')}\n"
f"</b>Likes:</b> {data.get('likes', 'N/A')}\n"
f"</b>Description:</b> {data.get('desc', 'N/A')}\n"
f"</b>Bio:</b> {data.get('bio', 'N/A')}"
),
parse_mode=enums.ParseMode.MARKDOWN,
)
else:
await message.edit("No data found for this TikTok user.")
await message.delete()
else:
await message.edit("An error occurred, please try again later.")
@Client.on_message(filters.command("ipinfo", prefix) & filters.me)
async def ipinfo(_, message: Message):
searchip = message.text.split(" ", 1)
if len(searchip) == 1:
await message.edit_text(f"Usage:{prefix}ipinfo [ip]")
return
searchip = searchip[1]
m = await message.edit_text("Searching...")
await m.edit_text("🔎")
try:
url = requests.get(
f"http://ip-api.com/json/{searchip}?fields=status,message,continent,continentCode,country,countryCode,region,regionName,city,district,zip,lat,lon,timezone,offset,currency,isp,org,as,asname,reverse,mobile,proxy,hosting,query"
)
response = json.loads(url.text)
text = f"""
<b>IP Address:</b> <code>{response['query']}</code>
<b>Status:</b> <code>{response['status']}</code>
<b>Continent Code:</b> <code>{response['continentCode']}</code>
<b>Country:</b> <code>{response['country']}</code>
<b>Country Code :</b> <code>{response['countryCode']}</code>
<b>Region:</b> <code>{response['region']}</code>
<b>Region Name :</b> <code>{response['regionName']}</code>
<b>City:</b> <code>{response['city']}</code>
<b>District:</b> <code>{response['district']}</code>
<b>ZIP:</b> <code>{response['zip']}</code>
<b>Latitude:</b> <code>{response['lat']}</code>
<b>Longitude:</b> <code>{response['lon']}</code>
<b>Time Zone:</b> <code>{response['timezone']}</code>
<b>Offset:</b> <code>{response['offset']}</code>
<b>Currency:</b> <code>{response['currency']}</code>
<b>ISP:</b> <code>{response['isp']}</code>
<b>Org:</b> <code>{response['org']}</code>
<b>As:</b> <code>{response['as']}</code>
<b>Asname:</b> <code>{response['asname']}</code>
<b>Reverse:</b> <code>{response['reverse']}</code>
<b>User is on Mobile:</b> <code>{response['mobile']}</code>
<b>Proxy:</b> <code>{response['proxy']}</code>
<b>Hosting:</b> <code>{response['hosting']}</code>"""
await m.edit_text(text)
except:
await m.edit_text("Unable To Find Info!")
@Client.on_message(filters.command("instastalk", prefix) & filters.me)
async def instagram_stalk(_, message: Message):
if len(message.command) > 1:
query = message.text.split(maxsplit=1)[1]
elif message.reply_to_message:
query = message.reply_to_message.text
else:
await message.edit(
f"Usage: <code>{prefix}instastalk <username></code> or reply to a message containing the username."
)
return
await message.edit("Fetching Instagram profile...")
url = f"{INSTAGRAM_API_URL}{query}"
response = requests.get(url)
if response.status_code == 200:
data = response.json().get("result", {}).get("user_info", {})
if data:
profile_pic_url = data.get("profile_pic_url", "")
profile_pic = requests.get(profile_pic_url).content
profile_pic_stream = io.BytesIO(profile_pic)
profile_pic_stream.name = "profile.jpg"
await message.reply_photo(
photo=profile_pic_stream,
caption=(
f"</b>Instagram Profile:</b>\n"
f"</b>Full Name:</b> {data.get('full_name', 'N/A')}\n"
f"</b>Username:</b> {data.get('username', 'N/A')}\n"
f"</b>Biography:</b> {data.get('biography', 'N/A')}\n"
f"</b>External URL:</b> {data.get('external_url', 'N/A')}\n"
f"</b>Posts:</b> {data.get('posts', 'N/A')}\n"
f"</b>Followers:</b> {data.get('followers', 'N/A')}\n"
f"</b>Following:</b> {data.get('following', 'N/A')}"
),
parse_mode=enums.ParseMode.MARKDOWN,
)
else:
await message.edit("No data found for this Instagram user.")
await message.delete()
else:
await message.edit("An error occurred, please try again later.")
@Client.on_message(filters.command("ghstalk", prefix) & filters.me)
async def github_stalk(_, message: Message):
if len(message.command) > 1:
query = message.text.split(maxsplit=1)[1]
elif message.reply_to_message:
query = message.reply_to_message.text
else:
await message.edit(
f"Usage: <code>{prefix}ghstalk <username></code> or reply to a message containing the username."
)
return
await message.edit("Fetching GitHub profile...")
url = f"{GH_STALK}{query}"
response = requests.get(url)
if response.status_code == 200:
data = response.json()
created_at = data.get("created_at", "N/A")
formatted_date = (
datetime.strptime(created_at, "%Y-%m-%dT%H:%M:%S%z")
if created_at != "N/A"
else None
)
if data:
await message.reply_photo(
photo=data.get("avatar_url", "").replace("?v=4", ""),
caption=f"</b>GitHub Profile:</b>\n"
f"</b>Name:</b> {data.get('name', 'N/A')}\n"
f"</b>Username:</b> {data.get('login', 'N/A')}\n"
f"</b>Bio:</b> {data.get('bio', 'N/A')}\n"
f"</b>Public Repositories:</b> <a href='{data.get('repos_url', '')}'>{data.get('public_repos', 'N/A')}</a>\n"
f"</b>Public Gists:</b> <a href='{data.get('gists_url', '')}'>{data.get('public_gists', 'N/A')}</a>\n"
f"</b>Company:</b> {data.get('company', 'N/A')}\n"
f"</b>Location:</b> {data.get('location', 'N/A')}\n"
f"</b>Email:</b> {data.get('email', 'N/A')}\n"
f"</b>Website:</b> {data.get('blog', 'N/A')}\n"
f"</b>Created At:</b> {formatted_date.strftime('%Y-%m-%d %I:%M:%S %p') if formatted_date else 'N/A'}\n"
f"</b>Hireable:</b> {data.get('hireable', 'N/A')}\n"
f"</b>Followers:</b> {data.get('followers', 'N/A')}\n"
f"</b>Following:</b> {data.get('following', 'N/A')}",
)
else:
await message.edit("No data found for this GitHub user.")
else:
await message.edit("An error occurred, please try again later.")
modules_help["socialstalk"] = {
"tiktokstalk [username]*": "Get TikTok profile information",
"ipinfo [IP address]*": "Get information about an IP address",
"instastalk [username]*": "Get Instagram profile information",
"ghstalk [username]*": "Get GitHub profile information",
}
+54
View File
@@ -0,0 +1,54 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import asyncio
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
commands = ["spam", "statspam", "slowspam", "fastspam"]
@Client.on_message(filters.command(commands, prefix) & filters.me)
async def spam(client: Client, message: Message):
amount = int(message.command[1])
text = " ".join(message.command[2:])
cooldown = {"spam": 0.15, "statspam": 0.1, "slowspam": 0.9, "fastspam": 0}
await message.delete()
for _msg in range(amount):
if message.reply_to_message:
sent = await message.reply_to_message.reply(text)
else:
sent = await client.send_message(message.chat.id, text)
if message.command[0] == "statspam":
await asyncio.sleep(0.1)
await sent.delete()
await asyncio.sleep(cooldown[message.command[0]])
modules_help["spam"] = {
"spam [amount] [text]": "Start spam",
"statspam [amount] [text]": "Send and delete",
"fastspam [amount] [text]": "Start fast spam",
"slowspam [amount] [text]": "Start slow spam",
}
+158
View File
@@ -0,0 +1,158 @@
import asyncio
import random
from io import BytesIO
import aiohttp
# noinspection PyUnresolvedReferences
from modules.squotes import render_message
from pyrogram import Client, enums, filters, types
from pyrogram.types import Message
# noinspection PyUnresolvedReferences
from utils.misc import modules_help, prefix
from utils.scripts import format_exc, import_library, resize_image
Image = import_library("PIL", "pillow").Image
np = import_library("numpy")
imageio = import_library("imageio")
def create_gif(filename: str, offset: int, fps: int = 2, typ: str = "spin"):
img = Image.open(f"downloads/{filename}")
if typ.lower() != "spin":
img = img.resize(
(random.randint(200, 1280), random.randint(200, 1280)), Image.ANTIALIAS
)
imageio.mimsave(
"downloads/video.gif",
[img.rotate(-(i % 360)) for i in range(1, 361, offset)],
fps=fps,
)
async def quote_cmd(client: Client, message: types.Message):
count = 1
is_png = False
send_for_me = False
no_reply = False
messages = []
async for msg in client.get_chat_history(
message.chat.id, offset_id=message.reply_to_message.id, reverse=True
):
if msg.empty:
continue
if msg.message_id >= message.id:
break
if no_reply:
msg.reply_to_message = None
messages.append(msg)
if len(messages) >= count:
break
if send_for_me:
await message.delete()
message = await client.send_message(
"me", "<b>Generating...</b>", parse_mode=enums.ParseMode.HTML
)
else:
await message.edit("<b>Generating...</b>", parse_mode=enums.ParseMode.HTML)
url = "https://quotes.fl1yd.su/generate"
params = {
"messages": [
await render_message(client, msg) for msg in messages if not msg.empty
],
"quote_color": "#162330",
"text_color": "#fff",
}
response = await aiohttp.ClientSession().post(url, json=params)
if response.status != 200:
return await message.edit(
f"<b>Quotes API error!</b>\n" f"<code>{response.text}</code>",
parse_mode=enums.ParseMode.HTML,
)
resized = resize_image(
BytesIO(await response.read()), img_type="PNG" if is_png else "WEBP"
)
return resized, is_png
@Client.on_message(filters.command(["spin", "dspin"], prefix) & filters.me)
async def spin_handler(client: Client, message: Message):
if not message.reply_to_message:
await message.edit(
"<b>Reply to a <i>message</i> to spin it!</b>",
parse_mode=enums.ParseMode.HTML,
)
await message.edit(
"<b>Downloading sticker...</b>", parse_mode=enums.ParseMode.HTML
)
return await message.edit(
"<b>Invalid file type!</b>", parse_mode=enums.ParseMode.HTML
)
try:
coro = True
if message.reply_to_message.document:
filename = message.reply_to_message.document.file_name
if (
not filename.endswith(".webp")
and not filename.endswith(".png")
and not filename.endswith(".jpg")
and not filename.endswith(".jpeg")
):
return await message.edit(
"<b>Invalid file type!</b>", parse_mode=enums.ParseMode.HTML
)
elif message.reply_to_message.sticker:
if message.reply_to_message.sticker.is_video:
return await message.edit(
"<b>Video stickers not allowed</b>", parse_mode=enums.ParseMode.HTML
)
filename = "sticker.webp"
elif message.reply_to_message.text:
result = await quote_cmd(client, message)
if result[1]:
filename = "sticker.png"
else:
filename = "sticker.webp"
open(f"downloads/" + filename, "wb").write(result[0].getbuffer())
coro = False
else:
filename = "photo.jpg"
if coro:
await message.reply_to_message.download(f"downloads/{filename}")
except Exception as ex:
return await message.edit(
f"<b>Message can not be loaded:</b>\n<code>{format_exc(ex)}</code>",
parse_mode=enums.ParseMode.HTML,
)
await message.edit("<b>Spinning...</b>", parse_mode=enums.ParseMode.HTML)
offset = int(message.command[1]) if len(message.command) > 1 else 10
fps = int(message.command[2]) if len(message.command) > 2 else 30
try:
loop = asyncio.get_event_loop()
await loop.run_in_executor(
None, lambda: create_gif(filename, offset, fps, message.command[0])
)
await message.delete()
return await client.send_animation(
chat_id=message.chat.id,
animation="downloads/video.gif",
reply_to_message_id=message.reply_to_message.id,
)
except Exception as e:
await message.reply(format_exc(e), parse_mode=enums.ParseMode.HTML)
modules_help["spin"] = {
"spin [offset] [fps]": "Spin message (Reply required)",
"dspin [offset] [fps]": "SHAKAL spin message (Reply required)",
}
+476
View File
@@ -0,0 +1,476 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import base64
from io import BytesIO
import requests
from pyrogram import Client, filters, errors, types
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import with_reply, format_exc, resize_image
QUOTES_API = "https://quotes-o042.onrender.com/generate"
@Client.on_message(filters.command(["q", "quote"], prefix) & filters.me)
@with_reply
async def quote_cmd(client: Client, message: Message):
if len(message.command) > 1 and message.command[1].isdigit():
count = int(message.command[1])
if count < 1:
count = 1
elif count > 15:
count = 15
else:
count = 1
is_png = "!png" in message.command or "!file" in message.command
send_for_me = "!me" in message.command or "!ls" in message.command
no_reply = "!noreply" in message.command or "!nr" in message.command
messages = []
async for msg in client.get_chat_history(
message.chat.id,
offset_id=message.reply_to_message.id + count,
limit=count,
):
if msg.empty:
continue
if msg.id >= message.id:
break
if no_reply:
msg.reply_to_message = None
messages.append(msg)
if len(messages) >= count:
break
messages.reverse()
if send_for_me:
await message.delete()
message = await client.send_message("me", "<b>Generating...</b>")
else:
await message.edit("<b>Generating...</b>")
params = {
"messages": [
await render_message(client, msg) for msg in messages if not msg.empty
],
"quote_color": "#162330",
"text_color": "#fff",
}
response = requests.post(QUOTES_API, json=params)
if not response.ok:
return await message.edit(
f"<b>Quotes API error!</b>\n<code>{response.text}</code>"
)
resized = resize_image(
BytesIO(response.content), img_type="PNG" if is_png else "WEBP"
)
await message.edit("<b>Sending...</b>")
try:
func = client.send_document if is_png else client.send_sticker
chat_id = "me" if send_for_me else message.chat.id
await func(chat_id, resized)
except errors.RPCError as e: # no rights to send stickers, etc
await message.edit(format_exc(e))
else:
await message.delete()
@Client.on_message(filters.command(["fq", "fakequote"], prefix) & filters.me)
@with_reply
async def fake_quote_cmd(client: Client, message: types.Message):
is_png = "!png" in message.command or "!file" in message.command
send_for_me = "!me" in message.command or "!ls" in message.command
no_reply = "!noreply" in message.command or "!nr" in message.command
fake_quote_text = " ".join(
[
arg
for arg in message.command[1:]
if arg not in ["!png", "!file", "!me", "!ls", "!noreply", "!nr"]
] # remove some special arg words
)
if not fake_quote_text:
return await message.edit("<b>Fake quote text is empty</b>")
q_message = await client.get_messages(message.chat.id, message.reply_to_message.id)
q_message.text = fake_quote_text
q_message.entities = None
if no_reply:
q_message.reply_to_message = None
if send_for_me:
await message.delete()
message = await client.send_message("me", "<b>Generating...</b>")
else:
await message.edit("<b>Generating...</b>")
params = {
"messages": [await render_message(client, q_message)],
"quote_color": "#162330",
"text_color": "#fff",
}
response = requests.post(QUOTES_API, json=params)
if not response.ok:
return await message.edit(
f"<b>Quotes API error!</b>\n<code>{response.text}</code>"
)
resized = resize_image(
BytesIO(response.content), img_type="PNG" if is_png else "WEBP"
)
await message.edit("<b>Sending...</b>")
try:
func = client.send_document if is_png else client.send_sticker
chat_id = "me" if send_for_me else message.chat.id
await func(chat_id, resized)
except errors.RPCError as e: # no rights to send stickers, etc
await message.edit(format_exc(e))
else:
await message.delete()
files_cache = {}
async def render_message(app: Client, message: types.Message) -> dict:
async def get_file(file_id) -> str:
if file_id in files_cache:
return files_cache[file_id]
content = await app.download_media(file_id, in_memory=True)
data = base64.b64encode(bytes(content.getbuffer())).decode()
files_cache[file_id] = data
return data
# text
if message.photo:
text = message.caption if message.caption else ""
elif message.poll:
text = get_poll_text(message.poll)
elif message.sticker:
text = ""
else:
text = get_reply_text(message)
# media
if message.photo:
media = await get_file(message.photo.file_id)
elif message.sticker:
media = await get_file(message.sticker.file_id)
else:
media = ""
# entities
entities = []
if message.entities:
for entity in message.entities:
entities.append(
{
"offset": entity.offset,
"length": entity.length,
"type": str(entity.type).split(".")[-1].lower(),
}
)
def move_forwards(msg: types.Message):
if msg.forward_origin:
if isinstance(msg.forward_origin, types.MessageOriginUser):
msg.from_user = msg.forward_origin.sender_user
elif isinstance(msg.forward_origin, types.MessageOriginHiddenUser):
msg.from_user.id = 0
msg.from_user.first_name = msg.forward_origin.sender_user_name
msg.from_user.last_name = ""
elif isinstance(msg.forward_origin, types.MessageOriginChat):
msg.sender_chat = msg.forward_origin.sender_chat
msg.from_user.id = 0
if msg.forward_origin.author_signature:
msg.author_signature = msg.forward_origin.author_signature
move_forwards(message)
# author
author = {}
if message.from_user and message.from_user.id != 0:
from_user = message.from_user
author["id"] = from_user.id
author["name"] = get_full_name(from_user)
if message.author_signature:
author["rank"] = message.author_signature
elif message.chat.type != "supergroup" or message.forward_date:
author["rank"] = ""
else:
try:
member = await message.chat.get_member(from_user.id)
except errors.UserNotParticipant:
author["rank"] = ""
else:
author["rank"] = getattr(member, "title", "") or (
"owner"
if member.status == "creator"
else "admin"
if member.status == "administrator"
else ""
)
if from_user.photo:
author["avatar"] = await get_file(from_user.photo.big_file_id)
elif not from_user.photo and from_user.username:
# may be user blocked us, we will try to get avatar via t.me
t_me_page = requests.get(f"https://t.me/{from_user.username}").text
sub = '<meta property="og:image" content='
index = t_me_page.find(sub)
if index != -1:
link = t_me_page[index + 35 :].split('"')
if (
len(link) > 0
and link[0]
and link[0] != "https://telegram.org/img/t_logo.png"
):
# found valid link
avatar = requests.get(link[0]).content
author["avatar"] = base64.b64encode(avatar).decode()
else:
author["avatar"] = ""
else:
author["avatar"] = ""
else:
author["avatar"] = ""
elif message.from_user and message.from_user.id == 0:
author["id"] = 0
author["name"] = message.from_user.first_name
author["rank"] = ""
else:
author["id"] = message.sender_chat.id
author["name"] = message.sender_chat.title
author["rank"] = "channel" if message.sender_chat.type == "channel" else ""
if message.sender_chat.photo:
author["avatar"] = await get_file(message.sender_chat.photo.big_file_id)
else:
author["avatar"] = ""
author["via_bot"] = message.via_bot.username if message.via_bot else ""
# reply
reply = {}
reply_msg = message.reply_to_message
if reply_msg and not reply_msg.empty:
move_forwards(reply_msg)
if reply_msg.from_user:
reply["id"] = reply_msg.from_user.id
reply["name"] = get_full_name(reply_msg.from_user)
else:
reply["id"] = reply_msg.sender_chat.id
reply["name"] = reply_msg.sender_chat.title
reply["text"] = get_reply_text(reply_msg)
return {
"text": text,
"media": media,
"entities": entities,
"author": author,
"reply": reply,
}
def get_audio_text(audio: types.Audio) -> str:
if audio.title and audio.performer:
return f" ({audio.title}{audio.performer})"
if audio.title:
return f" ({audio.title})"
if audio.performer:
return f" ({audio.performer})"
return ""
def get_reply_text(reply: types.Message) -> str:
return (
"📷 Photo" + ("\n" + reply.caption if reply.caption else "")
if reply.photo
else (
get_reply_poll_text(reply.poll)
if reply.poll
else (
"📍 Location"
if reply.location or reply.venue
else (
"👤 Contact"
if reply.contact
else (
"🖼 GIF"
if reply.animation
else (
"🎧 Music" + get_audio_text(reply.audio)
if reply.audio
else (
"📹 Video"
if reply.video
else (
"📹 Videomessage"
if reply.video_note
else (
"🎵 Voice"
if reply.voice
else (
(
reply.sticker.emoji + " "
if reply.sticker.emoji
else ""
)
+ "Sticker"
if reply.sticker
else (
"💾 File " + reply.document.file_name
if reply.document
else (
"🎮 Game"
if reply.game
else (
"🎮 set new record"
if reply.game_high_score
else (
f"{reply.dice.emoji} - {reply.dice.value}"
if reply.dice
else (
(
"👤 joined the group"
if reply.new_chat_members[
0
].id
== reply.from_user.id
else f"👤 invited {get_full_name(reply.new_chat_members[0])} to the group"
)
if reply.new_chat_members
else (
(
"👤 left the group"
if reply.left_chat_member.id
== reply.from_user.id
else f"👤 removed {get_full_name(reply.left_chat_member)}"
)
if reply.left_chat_member
else (
f"✏ changed group name to {reply.new_chat_title}"
if reply.new_chat_title
else (
"🖼 changed group photo"
if reply.new_chat_photo
else (
"🖼 removed group photo"
if reply.delete_chat_photo
else (
"📍 pinned message"
if reply.pinned_message
else (
"🎤 started a new video chat"
if reply.video_chat_started
else (
"🎤 ended the video chat"
if reply.video_chat_ended
else (
"🎤 invited participants to the video chat"
if reply.video_chat_members_invited
else (
"👥 created the group"
if reply.group_chat_created
or reply.supergroup_chat_created
else (
"👥 created the channel"
if reply.channel_chat_created
else reply.text
or "unsupported message"
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
def get_poll_text(poll: types.Poll) -> str:
text = get_reply_poll_text(poll) + "\n"
text += poll.question + "\n"
for option in poll.options:
text += f"- {option.text}"
if option.voter_count > 0:
text += f" ({option.voter_count} voted)"
text += "\n"
text += f"Total: {poll.total_voter_count} voted"
return text
def get_reply_poll_text(poll: types.Poll) -> str:
if poll.is_anonymous:
text = "📊 Anonymous poll" if poll.type == "regular" else "📊 Anonymous quiz"
else:
text = "📊 Poll" if poll.type == "regular" else "📊 Quiz"
if poll.is_closed:
text += " (closed)"
return text
def get_full_name(user: types.User) -> str:
name = user.first_name
if user.last_name:
name += " " + user.last_name
return name
modules_help["squotes"] = {
"q [reply]* [count 1-15] [!png] [!me] [!noreply]": "Generate a quote\n"
"Available options: !png — send as PNG, !me — send quote to"
"saved messages, !noreply — generate quote without reply",
"fq [reply]* [!png] [!me] [!noreply] [text]*": "Generate a fake quote",
}
+163
View File
@@ -0,0 +1,163 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import os
from io import BytesIO
from pyrogram import Client, filters, types, enums
from utils.misc import modules_help, prefix
from utils.scripts import (
with_reply,
interact_with,
interact_with_to_delete,
format_exc,
resize_image,
)
@Client.on_message(filters.command("kang", prefix) & filters.me)
@with_reply
async def kang(client: Client, message: types.Message):
await message.edit("<b>Please wait...</b>")
if len(message.command) < 2:
await message.edit(
"<b>No arguments provided\n"
f"Usage: <code>{prefix}kang [pack]* [emoji]</code></b>",
)
return
pack = message.command[1]
if len(message.command) >= 3:
emoji = message.command[2]
else:
emoji = ""
await client.unblock_user("@stickers")
await interact_with(
await client.send_message(
"@stickers", "/cancel", parse_mode=enums.ParseMode.MARKDOWN
)
)
await interact_with(
await client.send_message(
"@stickers", "/addsticker", parse_mode=enums.ParseMode.MARKDOWN
)
)
result = await interact_with(
await client.send_message(
"@stickers", pack, parse_mode=enums.ParseMode.MARKDOWN
)
)
if ".TGS" in result.text:
await message.edit("<b>Animated packs aren't supported</b>")
return
if "StickerExample.psd" not in result.text:
await message.edit(
"<b>Stickerpack doesn't exitst. Create it using @Stickers bot (via /newpack command)</b>",
)
return
try:
path = await message.reply_to_message.download()
except ValueError:
await message.edit(
"<b>Replied message doesn't contain any downloadable media</b>",
)
return
resized = resize_image(path)
if os.path.exists(path):
os.remove(path)
await interact_with(
await client.send_document(
"@stickers", resized, parse_mode=enums.ParseMode.MARKDOWN
)
)
response = await interact_with(
await client.send_message(
"@stickers", emoji, parse_mode=enums.ParseMode.MARKDOWN
)
)
if "/done" in response.text:
# ok
await interact_with(
await client.send_message(
"@stickers", "/done", parse_mode=enums.ParseMode.MARKDOWN
)
)
await client.delete_messages("@stickers", interact_with_to_delete)
await message.edit(
f"<b>Sticker added to <a href=https://t.me/addstickers/{pack}>pack</a></b>",
)
else:
await message.edit("<b>Something went wrong. Check history with @stickers</b>")
interact_with_to_delete.clear()
@Client.on_message(filters.command(["stp", "s2p", "stick2png"], prefix) & filters.me)
@with_reply
async def stick2png(client: Client, message: types.Message):
try:
await message.edit("<b>Downloading...</b>")
path = await message.reply_to_message.download()
with open(path, "rb") as f:
content = f.read()
if os.path.exists(path):
os.remove(path)
file_io = BytesIO(content)
file_io.name = "sticker.png"
await client.send_document(
message.chat.id, file_io, parse_mode=enums.ParseMode.MARKDOWN
)
except Exception as e:
await message.edit(format_exc(e))
else:
await message.delete()
@Client.on_message(filters.command(["resize"], prefix) & filters.me)
@with_reply
async def resize_cmd(client: Client, message: types.Message):
try:
await message.edit("<b>Downloading...</b>")
path = await message.reply_to_message.download()
resized = resize_image(path)
resized.name = "image.png"
if os.path.exists(path):
os.remove(path)
await client.send_document(
message.chat.id, resized, parse_mode=enums.ParseMode.MARKDOWN
)
except Exception as e:
await message.edit(format_exc(e))
else:
await message.delete()
modules_help["stickers"] = {
"kang [reply]* [pack]* [emoji]": "Add sticker to defined pack",
"stp [reply]*": "Convert replied sticker to PNG",
"resize [reply]*": "Resize replied image to 512xN format",
}
+88
View File
@@ -0,0 +1,88 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.types import Message
import random
import datetime
from utils.misc import modules_help, prefix, userbot_version, python_version, gitrepo
@Client.on_message(filters.command(["support", "repo"], prefix) & filters.me)
async def support(_, message: Message):
devs = ["@Qbtaumai", "@H4T3H46K3R"]
random.shuffle(devs)
commands_count = 0.0
for module in modules_help:
for _cmd in module:
commands_count += 1
await message.edit(
f"<b>Moon-Userbot\n\n"
"GitHub: <a href=https://github.com/The-MoonTg-project/Moon-Userbot>Moon-Userbot</a>\n"
"Custom modules repository: <a href=https://github.com/The-MoonTg-project/custom_modules>"
"custom_modules</a>\n"
"License: <a href=https://github.com/The-MoonTg-project/Moon-Userbot/blob/master/LICENSE>GNU GPL v3</a>\n\n"
"Channel: @moonuserbot\n"
"Custom modules: @moonub_modules\n"
"Chat [EN]: @moonub_chat\n"
f"Main developers: {', '.join(devs)}\n\n"
f"Python version: {python_version}\n"
f"Modules count: {len(modules_help) / 1}\n"
f"Commands count: {commands_count}</b>",
disable_web_page_preview=True,
)
@Client.on_message(filters.command(["version", "ver"], prefix) & filters.me)
async def version(client: Client, message: Message):
changelog = ""
ub_version = ".".join(userbot_version.split(".")[:2])
async for m in client.search_messages("moonuserbot", query=f"{userbot_version}."):
if ub_version in m.text:
changelog = m.message_id
await message.delete()
remote_url = list(gitrepo.remote().urls)[0]
commit_time = (
datetime.datetime.fromtimestamp(gitrepo.head.commit.committed_date)
.astimezone(datetime.timezone.utc)
.strftime("%Y-%m-%d %H:%M:%S %Z")
)
await message.reply(
f"<b>Moon Userbot version: {userbot_version}\n"
f"Changelog </b><i><a href=https://t.me/moonuserbot/{changelog}>in channel</a></i>.<b>\n"
f"Changelog written by </b><i>"
f"<a href=https://t.me/Qbtaumai>Abhi</a></i>\n\n"
+ (
f"<b>Branch: <a href={remote_url}/tree/{gitrepo.active_branch}>{gitrepo.active_branch}</a>\n"
if gitrepo.active_branch != "master"
else ""
)
+ f"Commit: <a href={remote_url}/commit/{gitrepo.head.commit.hexsha}>"
f"{gitrepo.head.commit.hexsha[:7]}</a> by {gitrepo.head.commit.author.name}\n"
f"Commit time: {commit_time}</b>",
)
modules_help["support"] = {
"support": "Information about userbot",
"version": "Check userbot version",
}
+43
View File
@@ -0,0 +1,43 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import os
from PIL import Image
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import prefix, modules_help
@Client.on_message(filters.command("setthumb", prefix) & filters.me)
async def setthumb(_, message: Message):
THUMB_PATH = "downloads/thumb"
if message.reply_to_message:
if not os.path.exists(THUMB_PATH):
os.makedirs(THUMB_PATH)
new_thumb = await message.reply_to_message.download()
with Image.open(new_thumb) as img:
if img.format in ["PNG", "JPG", "JPEG"]:
new_path = os.path.join(THUMB_PATH, "thumb.jpg")
os.rename(new_thumb, new_path)
await message.edit_text("Thumbnail set successfully!")
else:
await message.edit_text("Kindly reply to a PHOTO Entity!")
return
modules_help["thumb"] = {"setthumb [reply_to_photo]*": "set your own custom thumbnail"}
+43
View File
@@ -0,0 +1,43 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import asyncio
import time
from pyrogram import Client, filters
from pyrogram.errors import FloodWait
from pyrogram.types import Message
from utils.misc import modules_help, prefix
@Client.on_message(filters.command(["type", "typewriter"], prefix) & filters.me)
async def type_cmd(_, message: Message):
text = message.text.split(maxsplit=1)[1]
typed = ""
typing_symbol = ""
for char in text:
await message.edit(typed + typing_symbol)
await asyncio.sleep(0.1)
typed += char
await message.edit(typed)
await asyncio.sleep(0.1)
modules_help["type"] = {
"type</code> <code>| </code><code>typewriter [text]*": "Typing emulation. Don't use a lot of characters, you can receive a lot of floodwaits!"
}
+117
View File
@@ -0,0 +1,117 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import os
import sys
import shutil
import subprocess
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix, requirements_list
from utils.db import db
from utils.scripts import format_exc, restart
def check_command(command):
return shutil.which(command) is not None
@Client.on_message(filters.command("restart", prefix) & filters.me)
async def restart_cmd(_, message: Message):
db.set(
"core.updater",
"restart_info",
{
"type": "restart",
"chat_id": message.chat.id,
"message_id": message.id,
},
)
if "LAVHOST" in os.environ:
await message.edit("<b>Your lavHost is restarting...</b>")
os.system("lavhost restart")
return
await message.edit("<b>Restarting...</b>")
if os.path.exists("moonlogs.txt"):
os.remove("moonlogs.txt")
restart()
@Client.on_message(filters.command("update", prefix) & filters.me)
async def update(_, message: Message):
db.set(
"core.updater",
"restart_info",
{
"type": "update",
"chat_id": message.chat.id,
"message_id": message.id,
},
)
if "LAVHOST" in os.environ:
await message.edit("<b>Your lavHost is updating...</b>")
os.system("lavhost update")
return
await message.edit("<b>Updating...</b>")
try:
if not check_command("termux-setup-storage"):
subprocess.run(
[sys.executable, "-m", "pip", "install", "-U", "pip"], check=True
)
subprocess.run(["git", "pull"], check=True)
if (
os.path.exists("requirements.txt")
and os.path.getsize("requirements.txt") > 0
):
subprocess.run(
[
sys.executable,
"-m",
"pip",
"install",
"-U",
"-r",
"requirements.txt",
],
check=True,
)
if requirements_list:
subprocess.run(
[sys.executable, "-m", "pip", "install", "-U", *requirements_list],
check=True,
)
except Exception as e:
await message.edit(format_exc(e))
db.remove("core.updater", "restart_info")
else:
await message.edit("<b>Updating: done! Restarting...</b>")
if os.path.exists("moonlogs.txt"):
os.remove("moonlogs.txt")
restart()
modules_help["updater"] = {
"update": "Update the userbot. If new core modules are avaliable, they will be installed",
"restart": "Restart userbot",
}
+132
View File
@@ -0,0 +1,132 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import io
import os
import time
from pyrogram import Client, filters
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_exc, progress
@Client.on_message(filters.command("upl", prefix) & filters.me)
async def upl(client: Client, message: Message):
if len(message.command) > 1:
link = message.text.split(maxsplit=1)[1]
elif message.reply_to_message:
link = message.reply_to_message.text
else:
await message.edit(
f"<b>Usage: </b><code>{prefix}upl [filepath to upload]</code>"
)
return
if not os.path.isfile(link):
await message.edit(
f"<b>Error: </b><code>{link}</code> is not a valid file path."
)
return
try:
await message.edit("<b>Uploading Now...</b>")
await client.send_document(
message.chat.id,
link,
progress=progress,
progress_args=(message, time.time(), "<b>Uploading Now...</b>", link),
)
await message.delete()
except Exception as e:
await message.edit(format_exc(e))
@Client.on_message(filters.command("dlf", prefix) & filters.me)
async def dlf(client: Client, message: Message):
if message.reply_to_message:
await client.download_media(
message.reply_to_message,
progress=progress,
progress_args=(message, time.time(), "<b>Uploading Now...</b>"),
)
await message.edit("<b>Downloaded Successfully!</b>")
else:
await message.edit(f"<b>Usage: </b><code>{prefix}dlf [reply to a file]</code>")
@Client.on_message(filters.command("moonlogs", prefix) & filters.me)
async def mupl(client: Client, message: Message):
link = "moonlogs.txt"
if os.path.exists(link):
try:
await message.edit("<b>Uploading Now...</b>")
with open(link, "rb") as f:
data = f.read()
bio = io.BytesIO(data)
bio.name = "moonlogs.txt"
await client.send_document(
message.chat.id,
bio,
progress=progress,
progress_args=(message, time.time(), "<b>Uploading Now...</b>")
)
await message.delete()
except Exception as e:
await client.send_message(message.chat.id, format_exc(e))
else:
await message.edit("<b>Error: </b><code>LOGS</code> file doesn't exist.")
@Client.on_message(filters.command("uplr", prefix) & filters.me)
async def uplr(client: Client, message: Message):
if len(message.command) > 1:
link = message.text.split(maxsplit=1)[1]
elif message.reply_to_message:
link = message.reply_to_message.text
else:
await message.edit(
f"<b>Usage: </b><code>{prefix}upl [filepath to upload]</code>"
)
return
if not os.path.isfile(link):
await message.edit(
f"<b>Error: </b><code>{link}</code> is not a valid file path."
)
return
try:
await message.edit("<b>Uploading Now...</b>")
await client.send_document(
message.chat.id,
link,
progress=progress,
progress_args=(message, time.time(), "<b>Uploading Now...</b>", link),
)
await message.delete()
except Exception as e:
await message.edit(format_exc(e))
finally:
if os.path.exists(link):
os.remove(link)
modules_help["uplud"] = {
"upl [filepath]/[reply to path]*": "Upload a file from your local machine to Telegram",
"dlf": "Download a file from Telegram to your local machine",
"uplr [filepath]/[reply to path]*": "Upload a file from your local machine to Telegram, delete the file after uploading",
"moonlogs": "Upload the moonlogs.txt file to Telegram",
}
+285
View File
@@ -0,0 +1,285 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import asyncio
import math
import mimetypes
import os
import time
from datetime import datetime
from io import BytesIO
from urllib.parse import unquote
import requests
import urllib3
from pyrogram import Client, enums, filters
from pyrogram.types import Message
from pySmartDL import SmartDL
from utils.config import apiflash_key
from utils.misc import modules_help, prefix
from utils.scripts import format_exc, humanbytes, progress
def generate_screenshot(url):
api_url = f"https://api.apiflash.com/v1/urltoimage?access_key={apiflash_key}&url={url}&format=png"
response = requests.get(api_url)
if response.status_code == 200:
return BytesIO(response.content)
return None
http = urllib3.PoolManager()
@Client.on_message(filters.command("short", prefix) & filters.me)
async def short(_, message: Message):
if len(message.command) > 1:
link = message.text.split(maxsplit=1)[1]
elif message.reply_to_message:
link = message.reply_to_message.text
else:
await message.edit(f"<b>Usage: </b><code>{prefix}short [url to short]</code>")
return
r = http.request("GET", "https://clck.ru/--?url=" + link)
await message.edit(
r.data.decode().replace("https://", "<b>Shortened Url:</b>"),
disable_web_page_preview=True,
)
@Client.on_message(filters.command("urldl", prefix) & filters.me)
async def urldl(client: Client, message: Message):
if len(message.command) > 1:
message_id = None
link = message.text.split(maxsplit=1)[1]
elif message.reply_to_message:
message_id = message.reply_to_message.id
link = message.reply_to_message.text
else:
await message.edit(
f"<b>Usage: </b><code>{prefix}urldl [url to download]</code>"
)
return
await message.edit("<b>Trying to download...</b>")
c_time = time.time()
resp = requests.head(link, allow_redirects=True, timeout=5)
if resp.status_code != 200:
return await message.edit("<b>Failed to fetch request header information</b>")
content_type = resp.headers.get("Content-Type").split(";")[0]
extension = mimetypes.guess_extension(content_type)
# Check if the file is an executable binary
is_executable = content_type in [
"application/octet-stream",
"application/x-msdownload",
]
# Get the file extension from the URL
url_extension = os.path.splitext(link)[1].lower()
try:
os.makedirs("downloads")
if is_executable:
file_name = "downloads/" + link.split("/")[-1]
if not file_name.endswith(url_extension):
file_name += url_extension
elif extension:
file_name = "downloads/" + link.split("/")[-1]
if not file_name.endswith(extension):
file_name += extension
else:
file_name = "downloads/" + link.split("/")[-1]
except FileNotFoundError:
if is_executable:
file_name = "downloads/" + link.split("/")[-1]
if not file_name.endswith(url_extension):
file_name += url_extension
elif extension:
file_name = "downloads/" + link.split("/")[-1]
if not file_name.endswith(extension):
file_name += extension
else:
file_name = "downloads/" + link.split("/")[-1]
except FileExistsError:
if is_executable:
file_name = "downloads/" + link.split("/")[-1]
if not file_name.endswith(url_extension):
file_name += url_extension
elif extension:
file_name = "downloads/" + link.split("/")[-1]
if not file_name.endswith(extension):
file_name += extension
else:
file_name = "downloads/" + link.split("/")[-1]
downloader = SmartDL(link, file_name, progress_bar=False, timeout=10)
start_t = datetime.now()
try:
downloader.start(blocking=False)
except Exception as e:
return await message.edit_text(format_exc(e))
while not downloader.isFinished():
total_length = downloader.filesize or None
downloaded = downloader.get_dl_size(human=True)
u_m = ""
now = time.time()
diff = now - c_time
percentage = downloader.get_progress() * 100
speed = downloader.get_speed(human=True)
progress_str = (
"".join(["" for _ in range(math.floor(percentage / 5))])
+ "".join(["" for _ in range(20 - math.floor(percentage / 5))])
+ f"\n<b>Progress:</b> {round(percentage, 2)}%"
)
eta = downloader.get_eta(human=True)
try:
m = "<b>Trying to download...</b>\n"
m += f"<b>File Name:</b> <code>{unquote(link.split('/')[-1])}</code>\n"
m += f"<b>Speed:</b> {speed}\n"
m += f"{progress_str}\n"
m += f"{downloaded} of {humanbytes(total_length)}\n"
m += f"<b>ETA:</b> {eta}"
if round(diff % 10.00) == 0 and m != u_m:
await message.edit_text(disable_web_page_preview=True, text=m)
u_m = m
await asyncio.sleep(5)
except Exception as e:
await message.edit_text(format_exc(e))
if os.path.exists(file_name):
end_t = datetime.now()
sec = (end_t - start_t).seconds
await message.edit_text(
f"<b>Downloaded to <code>{file_name}</code> in {sec} seconds</b>"
)
ms_ = await message.edit("<b>Starting Upload...</b>")
await client.send_document(
message.chat.id,
file_name,
progress=progress,
progress_args=(ms_, c_time, "`Uploading...`"),
caption=f"<b>File Name:</b> <code>{unquote(link.split('/')[-1])}</code>\n",
reply_to_message_id=message_id,
)
await message.delete()
os.remove(file_name)
else:
await message.edit("<b>Failed to download</b>")
@Client.on_message(filters.command("upload", prefix) & filters.me)
async def upload_cmd(_, message: Message):
max_size = 512 * 1024 * 1024
max_size_mb = 100
min_file_age = 31
max_file_age = 180
ms_ = await message.edit("`Downloading...`", parse_mode=enums.ParseMode.MARKDOWN)
c_time = time.time()
try:
file_name = await message.download(
progress=progress, progress_args=(ms_, c_time, "`Downloading...`")
)
except ValueError:
try:
file_name = await message.reply_to_message.download(
progress=progress, progress_args=(ms_, c_time, "`Downloading...`")
)
except ValueError:
await message.edit("<b>File to upload not found</b>")
return
if os.path.getsize(file_name) > max_size:
await message.edit(f"<b>Files longer than {max_size_mb}MB isn't supported</b>")
if os.path.exists(file_name):
os.remove(file_name)
return
await message.edit("<b>Uploading...</b>")
with open(file_name, "rb") as f:
response = requests.post(
"https://x0.at",
files={"file": f},
)
if response.ok:
file_size_mb = os.path.getsize(file_name) / 1024 / 1024
file_age = int(
min_file_age
+ (max_file_age - min_file_age) * ((1 - (file_size_mb / max_size_mb)) ** 2)
)
url = response.text.replace("https://", "")
await message.edit(
f"<b>Your URL: {url}\nYour file will remain live for {file_age} days</b>",
disable_web_page_preview=True,
)
else:
await message.edit(
f"<b>API returned an error!\n{response.text}\n Not allowed</b>"
)
print(response.text)
if os.path.exists(file_name):
os.remove(file_name)
@Client.on_message(filters.command(["ws", "webshot"], prefix) & filters.me)
async def webshot(client: Client, message: Message):
if len(message.command) > 1:
url = message.text.split(maxsplit=1)[1]
if not url.startswith("https://"):
url = "https://" + message.text.split(maxsplit=1)[1]
elif message.reply_to_message:
url = message.reply_to_message.text
if not url.startswith("https://"):
url = "https://" + url
else:
await message.edit_text(
f"<b>Usage: </b><code>{prefix}webshot/{prefix}ws [url/reply to url]</code>"
)
return
chat_id = message.chat.id
await message.edit("<b>Generating screenshot...</b>")
try:
screenshot_data = generate_screenshot(url)
if screenshot_data:
await message.delete()
await client.send_photo(
chat_id, screenshot_data, caption=f"Screenshot of <code>{url}</code>"
)
else:
await message.edit_text(
"<code>Failed to generate screenshot...\nMake sure url is correct</code>"
)
except Exception as e:
await message.edit_text(f"An error occurred: {format_exc(e)}")
modules_help["url"] = {
"short [url]*": "short url",
"urldl [url]*": "download url content",
"upload [file|reply]*": "upload file to internet",
"webshot [link]*": "Screenshot of web page",
"ws [reply to link]*": "Screenshot of web page",
}
+115
View File
@@ -0,0 +1,115 @@
# Moon-Userbot - telegram userbot
# Copyright (C) 2020-present Moon Userbot Organization
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from pyrogram import Client, filters
from pyrogram.raw import functions
from pyrogram.types import Message
from utils.misc import modules_help, prefix
from utils.scripts import format_exc, interact_with, interact_with_to_delete
@Client.on_message(filters.command("inf", prefix) & filters.me)
async def get_user_inf(client: Client, message: Message):
if len(message.command) >= 2:
peer = await client.resolve_peer(message.command[1])
elif message.reply_to_message and message.reply_to_message.from_user:
peer = await client.resolve_peer(message.reply_to_message.from_user.id)
else:
peer = await client.resolve_peer("me")
response = await client.invoke(functions.users.GetFullUser(id=peer))
user = response.users[0]
full_user = response.full_user
if user.username is None:
username = "None"
else:
username = f"@{user.username}"
about = "None" if full_user.about is None else full_user.about
user_info = f"""|=<b>Username: {username}
|-Id: <code>{user.id}</code>
|-Bot: <code>{user.bot}</code>
|-Scam: <code>{user.scam}</code>
|-Name: <code>{user.first_name}</code>
|-Deleted: <code>{user.deleted}</code>
|-BIO: <code>{about}</code>
</b>"""
await message.edit(user_info)
@Client.on_message(filters.command("inffull", prefix) & filters.me)
async def get_full_user_inf(client: Client, message: Message):
await message.edit("<b>Receiving the information...</b>")
try:
if len(message.command) >= 2:
peer = await client.resolve_peer(message.command[1])
elif message.reply_to_message and message.reply_to_message.from_user:
peer = await client.resolve_peer(message.reply_to_message.from_user.id)
else:
peer = await client.resolve_peer("me")
response = await client.invoke(functions.users.GetFullUser(id=peer))
user = response.users[0]
full_user = response.full_user
await client.unblock_user("@creationdatebot")
try:
response = await interact_with(
await client.send_message("creationdatebot", f"/id {user.id}")
)
except RuntimeError:
creation_date = "None"
else:
creation_date = response.text
# await client.delete_messages("@creationdatebot", interact_with_to_delete)
interact_with_to_delete.clear()
if user.username is None:
username = "None"
else:
username = f"@{user.username}"
about = "None" if full_user.about is None else full_user.about
user_info = f"""|=<b>Username: {username}
|-Id: <code>{user.id}</code>
|-Account creation date: <code>{creation_date}</code>
|-Bot: <code>{user.bot}</code>
|-Scam: <code>{user.scam}</code>
|-Name: <code>{user.first_name}</code>
|-Deleted: <code>{user.deleted}</code>
|-BIO: <code>{about}</code>
|-Contact: <code>{user.contact}</code>
|-Can pin message: <code>{full_user.can_pin_message}</code>
|-Mutual contact: <code>{user.mutual_contact}</code>
|-Access hash: <code>{user.access_hash}</code>
|-Restricted: <code>{user.restricted}</code>
|-Verified: <code>{user.verified}</code>
|-Phone calls available: <code>{full_user.phone_calls_available}</code>
|-Phone calls private: <code>{full_user.phone_calls_private}</code>
|-Blocked: <code>{full_user.blocked}</code></b>"""
await message.edit(user_info)
except Exception as e:
await message.edit(format_exc(e))
modules_help["user_info"] = {
"inf [reply|id|username]": "Get brief information about user",
"inffull [reply|id|username": "Get full information about user",
}
+136
View File
@@ -0,0 +1,136 @@
# Copyright (C) 2020-2021 by DevsExpo@Github, < https://github.com/DevsExpo >.
#
# This file is part of < https://github.com/DevsExpo/FridayUserBot > project,
# and is released under the "GNU v3.0 License Agreement".
# Please see < https://github.com/DevsExpo/blob/master/LICENSE >
#
# All rights reserved.
import os
import time
import requests
from pyrogram import Client, enums, filters
from pyrogram.types import Message
from utils.config import vt_key as vak
from utils.misc import modules_help, prefix
from utils.scripts import edit_or_reply, format_exc, progress
@Client.on_message(filters.command("vt", prefix) & filters.me)
async def scan_my_file(_, message: Message):
ms_ = await edit_or_reply(message, "`Please Wait! Scanning This File`")
if not message.reply_to_message:
return await ms_.edit(
"`Please Reply To File To Scan For Viruses`",
parse_mode=enums.ParseMode.MARKDOWN,
)
if not message.reply_to_message.document:
return await ms_.edit(
"`Please Reply To File To Scan For Viruses`",
parse_mode=enums.ParseMode.MARKDOWN,
)
if vak is None:
return await ms_.edit(
"`You Need To Set VIRUSTOTAL_API_KEY For Functing Of This Plugin.`",
parse_mode=enums.ParseMode.MARKDOWN,
)
if int(message.reply_to_message.document.file_size) > 32000000:
return await ms_.edit(
f"**File Too Large, Use `{prefix}vtl` instead**",
parse_mode=enums.ParseMode.MARKDOWN,
)
c_time = time.time()
downloaded_file_name = await message.reply_to_message.download(
progress=progress,
progress_args=(ms_, c_time, "`Downloading This File!`"),
)
url = "https://www.virustotal.com/vtapi/v2/file/scan"
params = {"apikey": vak}
files = {"file": (downloaded_file_name, open(downloaded_file_name, "rb"))}
response = requests.post(url, files=files, params=params, timeout=10)
try:
r_json = response.json()
md5 = r_json["md5"]
except Exception as e:
return await ms_.edit(format_exc(e))
await ms_.edit(
f'<b><u>Scanned {message.reply_to_message.document.file_name}</b></u>. <b>You Can Visit :</b> <a href="https://www.virustotal.com/gui/file/{md5}">Here</a> <b>In 5-10 Min To See File Report</b>'
)
if os.path.exists(downloaded_file_name):
os.remove(downloaded_file_name)
@Client.on_message(filters.command("vtl", prefix) & filters.me)
async def scan_my_large_file(_, message: Message):
ms_ = await edit_or_reply(message, "`Please Wait! Scanning This File`")
if not message.reply_to_message:
return await ms_.edit(
"`Please Reply To File To Scan For Viruses`",
parse_mode=enums.ParseMode.MARKDOWN,
)
if not message.reply_to_message.document:
return await ms_.edit(
"`Please Reply To File To Scan For Viruses`",
parse_mode=enums.ParseMode.MARKDOWN,
)
if vak is None:
return await ms_.edit(
"`You Need To Set VIRUSTOTAL_API_KEY For Functing Of This Plugin.`",
parse_mode=enums.ParseMode.MARKDOWN,
)
if int(message.reply_to_message.document.file_size) > 650000000:
return await ms_.edit(
"**File Too Large, exceeded Max capacity of 650MB**",
parse_mode=enums.ParseMode.MARKDOWN,
)
c_time = time.time()
downloaded_file_name = await message.reply_to_message.download(
progress=progress,
progress_args=(ms_, c_time, "`Downloading This File!`"),
)
url1 = "https://www.virustotal.com/api/v3/files/upload_url"
headers = {"accept": "application/json", "x-apikey": vak}
rponse = requests.get(url1, headers=headers, timeout=10)
try:
r_json = rponse.json()
upl_data = r_json["data"]
except Exception as e:
return await ms_.edit(format_exc(e))
url = upl_data
files = {"file": (downloaded_file_name, open(downloaded_file_name, "rb"))}
headers = {"accept": "application/json", "x-apikey": vak}
response = requests.post(url, files=files, headers=headers, timeout=10)
r_json = response.json()
analysis_url = r_json["data"]["links"]["self"]
url = analysis_url
headers = {"accept": "application/json", "x-apikey": vak}
response_result = requests.get(url, headers=headers, timeout=10)
try:
r_json = response_result.json()
md5 = r_json["meta"]["file_info"]["md5"]
except Exception as e:
return await ms_.edit(format_exc(e))
await ms_.edit(
f'<b><u>Scanned {message.reply_to_message.document.file_name}</b></u>. <b>You Can Visit :</b> <a href="https://www.virustotal.com/gui/file/{md5}">Here</a> <b>In 5-10 Min To See File Report</b>'
)
if os.path.exists(downloaded_file_name):
os.remove(downloaded_file_name)
modules_help["virustotal"] = {
"vt [reply to file]*": "Scan for viruses on Virus Total (for lower file size <32MB)",
"vtl [reply to file]*": "Scan for viruses on Virus Total (for lower file size >=32MB)",
}