""" Extol Wallet & Payment Integration for DragMusic Bot Commands: /addapi (private chat only) /addextol
/removeextol /payextol /checkextol /extolbal /sendextol """ import os import httpx from pyrogram import filters from DragMusic import app from DragMusic.utils.database import mongodb from pyrogram.types import Message from datetime import datetime from pyrogram.enums import ParseMode API_BASE_URL = "https://marketapi.animerealms.org" api_keys_collection = mongodb.iac_api_keys addresses_collection = mongodb.iac_extol_addresses payments_collection = mongodb.iac_payments # Async helpers for MongoDB async def set_user_api_key(user_id: int, api_key: str): await api_keys_collection.update_one( {"user_id": user_id}, {"$set": {"api_key": api_key}}, upsert=True ) async def get_user_api_key(user_id: int): doc = await api_keys_collection.find_one({"user_id": user_id}) return doc["api_key"] if doc and "api_key" in doc else None async def set_user_address(user_id: int, address: str): await addresses_collection.update_one( {"user_id": user_id}, {"$set": {"address": address}}, upsert=True ) async def get_user_address(user_id: int): doc = await addresses_collection.find_one({"user_id": user_id}) return doc["address"] if doc and "address" in doc else None async def remove_user_address(user_id: int): await addresses_collection.delete_one({"user_id": user_id}) async def set_last_payment_id(user_id: int, payment_id: str): await payments_collection.update_one( {"user_id": user_id}, {"$set": {"last_payment_id": payment_id}}, upsert=True ) async def get_last_payment_id(user_id: int): doc = await payments_collection.find_one({"user_id": user_id}) return doc["last_payment_id"] if doc and "last_payment_id" in doc else None async def save_payment(user_id: int, payment_id: str, address: str, amount: float, payment_url: str): await payments_collection.insert_one({ "user_id": user_id, "payment_id": payment_id, "address": address, "amount": amount, "payment_url": payment_url, "created_at": datetime.utcnow() }) async def get_user_payments(user_id: int, limit: int = 10): cursor = payments_collection.find({"user_id": user_id}).sort("created_at", -1).limit(limit) return await cursor.to_list(length=limit) # /addapi (private chat only) @app.on_message(filters.command("addapi") & filters.private) async def set_api_key_handler(client, message: Message): args = message.text.split() if len(args) != 2: await message.reply_text("Usage: /addapi ") return await set_user_api_key(message.from_user.id, args[1]) await message.reply_text("✅ Extol API Key set successfully.") # Helper to check API key async def check_api_key(message: Message): user_id = message.from_user.id api_key = await get_user_api_key(user_id) if not api_key: await message.reply_text("[IAC Marketplace] API key not set. Use /addapi in bot DM to set it.") return None return api_key # /addextol
@app.on_message(filters.command("addextol")) async def add_extol_handler(client, message: Message): args = message.text.split() if len(args) != 2 or not args[1].startswith("EXT"): await message.reply_text("❌ Provide a valid Extol address starting with EXT.\n Usage: /addextol
") return await set_user_address(message.from_user.id, args[1]) await message.reply_text(f"✅ Extol address saved: `{args[1]}`.") # /removeextol @app.on_message(filters.command("removeextol")) async def remove_extol_handler(client, message: Message): await remove_user_address(message.from_user.id) await message.reply_text("✅ Extol address removed.") # /payextol @app.on_message(filters.command("payextol")) async def pay_extol_handler(client, message: Message): args = message.text.split() if len(args) != 2 or not args[1].isdigit(): await message.reply_text("❌ Enter a valid numeric amount.\n Usage: /payextol ") return address = await get_user_address(message.from_user.id) if not address: await message.reply_text("❌ Use /addextol
to set your address first.") return msg = await message.reply_text("🔗 Generating payment link...") data = {"address": address, "amount": int(args[1])} resp = await extol_request(message.from_user.id, "/api/create-payment", method="POST", data=data) if not resp.get("ok"): return await msg.edit(f"❌ Error: `{resp.get('error')}`") payment_id = resp["payment_id"] await set_last_payment_id(message.from_user.id, payment_id) # Save payment to history for /checkextol await save_payment(message.from_user.id, payment_id, address, int(args[1]), resp["payment_url"]) await msg.edit(f"✅ Click here to pay", disable_web_page_preview=True, parse_mode=ParseMode.HTML) # /checkextol @app.on_message(filters.command("checkextol")) async def check_extol_handler(client, message: Message): payments = await get_user_payments(message.from_user.id, limit=10) if not payments: await message.reply_text("❌ No recent payments found.") return msg = await message.reply_text("🔍 Checking last 10 payment statuses...") status_lines = [] for p in payments: payment_id = p["payment_id"] amount = p["amount"] pay_url = p["payment_url"] resp = await extol_request(message.from_user.id, "/api/payment-status", params={"payment_id": payment_id}) if not resp.get("ok"): status_str = f"❌ Error: {resp.get('error') or 'Unknown'}" else: status = resp["status"] if status == "paid": status_str = f"✅ Paid
From: {resp.get('from_address', '-')}, At: {resp.get('paid_at', '-')}" elif status == "timeout": status_str = f"⌛ Timeout
Expired: {resp.get('expired_at', '-')}" else: status_str = "⏳ Pending" status_lines.append(f"Amount: {amount}
" f'Click here to pay
' f"ID: {payment_id}
{status_str}") await msg.edit("\n\n".join(status_lines), disable_web_page_preview=True, parse_mode=ParseMode.HTML) # /extolbal @app.on_message(filters.command("extolbal")) async def extol_balance_handler(client, message: Message): msg = await message.reply_text("🔍 Fetching Extol balance...") resp = await extol_request(message.from_user.id, "/api/balance") if not resp.get("ok"): return await msg.edit(f"❌ Error: `{resp.get('error')}`") balance = resp.get("balance", 0) address = resp.get("address", "Unknown") await msg.edit(f"💰 Balance: {balance} EXT\n🏷️ Address: {address}") # /sendextol @app.on_message(filters.command("sendextol")) async def send_extol_handler(client, message: Message): args = message.text.split() if len(args) != 3 or not args[2].isdigit() or not args[1].startswith("EXT"): await message.reply_text("Usage: /sendextol ") return to_address, amt = args[1], int(args[2]) if amt <= 0: await message.reply_text("❌ Amount must be positive.") return msg = await message.reply_text("🔄 Sending Extol...") resp = await extol_request( message.from_user.id, "/api/withdraw", method="GET", params={"amount": amt, "address": to_address}, ) if not resp.get("ok"): error_msg = resp.get('error') or 'Unknown error (no message from API)' code = resp.get('code') if code is not None: error_msg = f"(code {code}) {error_msg}" return await msg.edit(f"❌ Error: {error_msg}") link = resp.get("link", "No explorer link.") await msg.edit(f"✅ Sent {amt} EXT to {to_address} \nView Transaction", disable_web_page_preview=True, parse_mode=ParseMode.HTML) # --- HTTPX helper --- async def extol_request(user_id, path, method="GET", data=None, params=None): api_key = await get_user_api_key(user_id) if not api_key: return {"ok": False, "error": "API key not set. Use /addapi in DM."} async with httpx.AsyncClient() as client: headers = {"api-key": api_key} try: if method == "GET": r = await client.get(f"{API_BASE_URL}{path}", headers=headers, params=params, timeout=10) else: r = await client.post(f"{API_BASE_URL}{path}", headers=headers, json=data, timeout=10) return r.json() except Exception as e: return {"ok": False, "error": str(e)}