init, .gitignore
This commit is contained in:
@@ -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>",
|
||||
}
|
||||
@@ -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",
|
||||
}
|
||||
@@ -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>",
|
||||
}
|
||||
@@ -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",
|
||||
}
|
||||
@@ -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",
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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",
|
||||
}
|
||||
@@ -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.",
|
||||
}
|
||||
@@ -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",
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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]",
|
||||
}
|
||||
@@ -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 "
|
||||
}
|
||||
Reference in New Issue
Block a user