refactor: extract userbot to standalone repo, add as git submodule
Deploy to Server / deploy (push) Has been cancelled
Deploy to Server / deploy (push) Has been cancelled
userbot now lives at ssh://git@gitssh.forust.xyz:2221/forust/userbot.git and is included in homelab as a submodule at userbot/
This commit is contained in:
@@ -1,57 +0,0 @@
|
||||
from os import listdir
|
||||
|
||||
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
|
||||
|
||||
|
||||
@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(
|
||||
f'Failed to back up the database!\n\n{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>',
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
# Moon-Userbot - telegram userbot
|
||||
# Copyright (C) 2020-present Moon Userbot Organization
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
from pyrogram import Client, filters
|
||||
from pyrogram.errors import MessageTooLong
|
||||
from pyrogram.types import Message
|
||||
from utils.db import db
|
||||
from utils.misc import modules_help, prefix
|
||||
|
||||
|
||||
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 and 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',
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from pyrogram import Client, enums, filters
|
||||
from pyrogram.types import Message
|
||||
from utils import config
|
||||
from utils.db import db
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
from utils.misc import modules_help, prefix
|
||||
from utils.scripts import format_exc, restart
|
||||
|
||||
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(
|
||||
'<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='<b>Database backup complete!\nType: </b>'
|
||||
'<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(
|
||||
'<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='<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/')
|
||||
|
||||
try:
|
||||
mod = message.text.split(maxsplit=1)[1].split('.')[0]
|
||||
except Exception:
|
||||
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/')
|
||||
|
||||
try:
|
||||
mod = message.text.split(maxsplit=1)[1].split('.')[0]
|
||||
except Exception:
|
||||
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='<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': '<b>Backup database</b>',
|
||||
'restore [reply]': '<b>Restore database</b>',
|
||||
'backupmod [name]': '<b>Backup mod</b>',
|
||||
'backupmods': '<b>Backup all mods</b>',
|
||||
'resmod [name]': '<b>Restore mod</b>',
|
||||
'resmods': '<b>Restore all mods</b>',
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
import requests
|
||||
from pyrogram import Client, filters
|
||||
from utils.misc import modules_help, prefix
|
||||
from utils.scripts import format_exc, import_library
|
||||
|
||||
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, timeout=10)
|
||||
|
||||
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.get('description', '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',
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
import asyncio
|
||||
import os
|
||||
from collections import defaultdict
|
||||
|
||||
from pyrogram import Client, filters
|
||||
from pyrogram.errors import (
|
||||
FileReferenceExpired,
|
||||
FileReferenceInvalid,
|
||||
TopicClosed,
|
||||
TopicDeleted,
|
||||
)
|
||||
from pyrogram.types import Message
|
||||
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('custom.mlog', str(group_id), {})
|
||||
|
||||
|
||||
# Helper to update group-specific data
|
||||
def update_group_data(group_id, data):
|
||||
db.set('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',
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
from datetime import datetime
|
||||
|
||||
import aiohttp
|
||||
from pyrogram import Client, filters
|
||||
from pyrogram.types import Message
|
||||
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'
|
||||
}
|
||||
@@ -1,519 +0,0 @@
|
||||
# Moon-Userbot - telegram userbot
|
||||
# Copyright (C) 2020-present Moon Userbot Organization
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import base64
|
||||
import os
|
||||
from io import BytesIO
|
||||
|
||||
import aiofiles
|
||||
import aiohttp
|
||||
import requests
|
||||
from PIL import Image, ImageEnhance
|
||||
from pyrogram import Client, enums, filters
|
||||
from pyrogram.errors import MediaCaptionTooLong, MessageTooLong
|
||||
from pyrogram.types import InputMediaPhoto, Message
|
||||
from utils.misc import modules_help, prefix
|
||||
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, 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, timeout=10)
|
||||
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, timeout=10)
|
||||
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, timeout=10).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, timeout=10)
|
||||
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, timeout=10).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, timeout=10)
|
||||
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, timeout=10)
|
||||
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',
|
||||
}
|
||||
@@ -1,504 +0,0 @@
|
||||
# Moon-Userbot - telegram userbot
|
||||
# Copyright (C) 2020-present Moon Userbot Organization
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import asyncio
|
||||
import contextlib
|
||||
import os
|
||||
|
||||
import requests
|
||||
from modules.url import generate_screenshot
|
||||
from pyrogram import Client, enums, filters
|
||||
from pyrogram.types import Message
|
||||
from utils.misc import modules_help, prefix
|
||||
from utils.scripts import 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 = '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]
|
||||
with contextlib.suppress(BaseException):
|
||||
await client.delete_messages(chat_id, message_id)
|
||||
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, timeout=10)
|
||||
|
||||
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, timeout=10)
|
||||
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, timeout=10)
|
||||
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, timeout=10)
|
||||
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, timeout=10)
|
||||
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, timeout=10)
|
||||
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, timeout=10)
|
||||
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'], timeout=10)
|
||||
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, timeout=10)
|
||||
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, timeout=10)
|
||||
|
||||
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.',
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
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(
|
||||
f'<b>You already have a search in progress!\nType: <code>{prefix}scancel</code> to cancel it.</b>',
|
||||
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 Exception:
|
||||
return await message.edit(
|
||||
f'<b>Usage:</b> <code>{prefix}search [/cmd]* [search_word]* [timeout=2.0]</code>',
|
||||
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',
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
# copyright by https/t.me/shado_hackers
|
||||
|
||||
from pyrogram import Client, filters
|
||||
from pyrogram.types import Message
|
||||
from utils.misc import modules_help, prefix
|
||||
from utils.scripts import format_exc, import_library
|
||||
|
||||
import_library('lxml_html_clean')
|
||||
import_library('newspaper', 'newspaper3k')
|
||||
nltk = import_library('nltk')
|
||||
from newspaper import Article # noqa: E402
|
||||
from newspaper.article import ArticleException # noqa: E402
|
||||
|
||||
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'}
|
||||
@@ -1,46 +0,0 @@
|
||||
# Moon-Userbot - telegram userbot
|
||||
# Copyright (C) 2020-present Moon Userbot Organization
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
from pyrogram import Client, enums, filters
|
||||
from pyrogram.types import Message
|
||||
from utils.misc import modules_help, prefix
|
||||
|
||||
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]',
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
import os
|
||||
import time
|
||||
|
||||
import requests
|
||||
from pyrogram import Client, enums, filters
|
||||
from pyrogram.errors import MessageTooLong
|
||||
from pyrogram.types import Message
|
||||
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, timeout=10)
|
||||
else:
|
||||
response = requests.get(url, headers=headers, timeout=10)
|
||||
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('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