File size: 9,049 Bytes
65dca5a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70624fc
 
65dca5a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63ef879
65dca5a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e8b3130
65dca5a
 
 
 
 
 
 
49650a3
65dca5a
 
 
 
 
 
 
 
 
 
5daaff6
65dca5a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49650a3
65dca5a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
"""
Extol Wallet & Payment Integration for DragMusic Bot

Commands:
/addapi <api_key> (private chat only)
/addextol <address>
/removeextol
/payextol <amount>
/checkextol
/extolbal
/sendextol <to_address> <amount>
"""

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 <api_key> (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 <your_api_key>")
        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 <your_api_key> in bot DM to set it.")
        return None
    return api_key

# /addextol <address>
@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 <address>")
        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 <amount>
@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 <amount>")
        return
    address = await get_user_address(message.from_user.id)
    if not address:
        await message.reply_text("❌ Use /addextol <address> 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"βœ… <a href='{resp['payment_url']}'>Click here to pay</a>", 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"βœ… <b>Paid</b><br>From: <code>{resp.get('from_address', '-')}</code>, At: <code>{resp.get('paid_at', '-')}</code>"
            elif status == "timeout":
                status_str = f"βŒ› <b>Timeout</b><br>Expired: <code>{resp.get('expired_at', '-')}</code>"
            else:
                status_str = "⏳ <b>Pending</b>"
        status_lines.append(f"Amount: <code>{amount}</code><br>"
                          f'<a href="{pay_url}">Click here to pay</a><br>'
                          f"ID: <code>{payment_id}</code><br>{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 <to_address> <amount>
@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 <to_address> <amount>")
        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} \n<a href='{link}'>View Transaction</a>", 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 <key> 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)}