init, .gitignore

This commit is contained in:
2025-11-11 00:02:49 +01:00
commit 4e18cd0eb3
124 changed files with 16300 additions and 0 deletions
+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 "
}