taslim19 commited on
Commit
65dca5a
Β·
1 Parent(s): 6f39b38

fix: make payment and transaction links clickable in extol plugin

Browse files
Files changed (1) hide show
  1. DragMusic/plugins/games/extol.py +217 -0
DragMusic/plugins/games/extol.py ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Extol Wallet & Payment Integration for DragMusic Bot
3
+
4
+ Commands:
5
+ /addapi <api_key> (private chat only)
6
+ /addextol <address>
7
+ /removeextol
8
+ /payextol <amount>
9
+ /checkextol
10
+ /extolbal
11
+ /sendextol <to_address> <amount>
12
+ """
13
+
14
+ import os
15
+ import httpx
16
+ from pyrogram import filters
17
+ from DragMusic import app
18
+ from DragMusic.utils.database import mongodb
19
+ from pyrogram.types import Message
20
+ from datetime import datetime
21
+
22
+ API_BASE_URL = "https://marketapi.animerealms.org"
23
+ api_keys_collection = mongodb.iac_api_keys
24
+ addresses_collection = mongodb.iac_extol_addresses
25
+ payments_collection = mongodb.iac_payments
26
+
27
+ # Async helpers for MongoDB
28
+ async def set_user_api_key(user_id: int, api_key: str):
29
+ await api_keys_collection.update_one(
30
+ {"user_id": user_id},
31
+ {"$set": {"api_key": api_key}},
32
+ upsert=True
33
+ )
34
+
35
+ async def get_user_api_key(user_id: int):
36
+ doc = await api_keys_collection.find_one({"user_id": user_id})
37
+ return doc["api_key"] if doc and "api_key" in doc else None
38
+
39
+ async def set_user_address(user_id: int, address: str):
40
+ await addresses_collection.update_one(
41
+ {"user_id": user_id},
42
+ {"$set": {"address": address}},
43
+ upsert=True
44
+ )
45
+
46
+ async def get_user_address(user_id: int):
47
+ doc = await addresses_collection.find_one({"user_id": user_id})
48
+ return doc["address"] if doc and "address" in doc else None
49
+
50
+ async def remove_user_address(user_id: int):
51
+ await addresses_collection.delete_one({"user_id": user_id})
52
+
53
+ async def set_last_payment_id(user_id: int, payment_id: str):
54
+ await payments_collection.update_one(
55
+ {"user_id": user_id},
56
+ {"$set": {"last_payment_id": payment_id}},
57
+ upsert=True
58
+ )
59
+
60
+ async def get_last_payment_id(user_id: int):
61
+ doc = await payments_collection.find_one({"user_id": user_id})
62
+ return doc["last_payment_id"] if doc and "last_payment_id" in doc else None
63
+
64
+ async def save_payment(user_id: int, payment_id: str, address: str, amount: float, payment_url: str):
65
+ await payments_collection.insert_one({
66
+ "user_id": user_id,
67
+ "payment_id": payment_id,
68
+ "address": address,
69
+ "amount": amount,
70
+ "payment_url": payment_url,
71
+ "created_at": datetime.utcnow()
72
+ })
73
+
74
+ async def get_user_payments(user_id: int, limit: int = 10):
75
+ cursor = payments_collection.find({"user_id": user_id}).sort("created_at", -1).limit(limit)
76
+ return await cursor.to_list(length=limit)
77
+
78
+ # /addapi <api_key> (private chat only)
79
+ @app.on_message(filters.command("addapi") & filters.private)
80
+ async def set_api_key_handler(client, message: Message):
81
+ args = message.text.split()
82
+ if len(args) != 2:
83
+ await message.reply_text("Usage: /addapi <your_api_key>")
84
+ return
85
+ await set_user_api_key(message.from_user.id, args[1])
86
+ await message.reply_text("βœ… Extol API Key set successfully.")
87
+
88
+ # Helper to check API key
89
+ async def check_api_key(message: Message):
90
+ user_id = message.from_user.id
91
+ api_key = await get_user_api_key(user_id)
92
+ if not api_key:
93
+ await message.reply_text("[IAC Marketplace] API key not set. Use /addapi <your_api_key> in bot DM to set it.")
94
+ return None
95
+ return api_key
96
+
97
+ # /addextol <address>
98
+ @app.on_message(filters.command("addextol"))
99
+ async def add_extol_handler(client, message: Message):
100
+ args = message.text.split()
101
+ if len(args) != 2 or not args[1].startswith("EXT"):
102
+ await message.reply_text("❌ Provide a valid Extol address starting with EXT.\n Usage: /addextol <address>")
103
+ return
104
+ await set_user_address(message.from_user.id, args[1])
105
+ await message.reply_text(f"βœ… Extol address saved: `{args[1]}`.")
106
+
107
+ # /removeextol
108
+ @app.on_message(filters.command("removeextol"))
109
+ async def remove_extol_handler(client, message: Message):
110
+ await remove_user_address(message.from_user.id)
111
+ await message.reply_text("βœ… Extol address removed.")
112
+
113
+ # /payextol <amount>
114
+ @app.on_message(filters.command("payextol"))
115
+ async def pay_extol_handler(client, message: Message):
116
+ args = message.text.split()
117
+ if len(args) != 2 or not args[1].isdigit():
118
+ await message.reply_text("❌ Enter a valid numeric amount.\n Usage: /payextol <amount>")
119
+ return
120
+ address = await get_user_address(message.from_user.id)
121
+ if not address:
122
+ await message.reply_text("❌ Use /addextol <address> to set your address first.")
123
+ return
124
+ msg = await message.reply_text("πŸ”— Generating payment link...")
125
+ data = {"address": address, "amount": int(args[1])}
126
+ resp = await extol_request(message.from_user.id, "/api/create-payment", method="POST", data=data)
127
+ if not resp.get("ok"):
128
+ return await msg.edit(f"❌ Error: `{resp.get('error')}`")
129
+ payment_id = resp["payment_id"]
130
+ await set_last_payment_id(message.from_user.id, payment_id)
131
+ # Save payment to history for /checkextol
132
+ await save_payment(message.from_user.id, payment_id, address, int(args[1]), resp["payment_url"])
133
+ await msg.edit(f"βœ… <a href='{resp['payment_url']}'>Click here to pay</a>", disable_web_page_preview=True, parse_mode="html")
134
+
135
+ # /checkextol
136
+ @app.on_message(filters.command("checkextol"))
137
+ async def check_extol_handler(client, message: Message):
138
+ payments = await get_user_payments(message.from_user.id, limit=10)
139
+ if not payments:
140
+ await message.reply_text("❌ No recent payments found.")
141
+ return
142
+ msg = await message.reply_text("πŸ” Checking last 10 payment statuses...")
143
+ status_lines = []
144
+ for p in payments:
145
+ payment_id = p["payment_id"]
146
+ amount = p["amount"]
147
+ pay_url = p["payment_url"]
148
+ resp = await extol_request(message.from_user.id, "/api/payment-status", params={"payment_id": payment_id})
149
+ if not resp.get("ok"):
150
+ status_str = f"❌ Error: {resp.get('error') or 'Unknown'}"
151
+ else:
152
+ status = resp["status"]
153
+ if status == "paid":
154
+ status_str = f"βœ… <b>Paid</b><br>From: <code>{resp.get('from_address', '-')}", At: <code>{resp.get('paid_at', '-')}</code>"
155
+ elif status == "timeout":
156
+ status_str = f"βŒ› <b>Timeout</b><br>Expired: <code>{resp.get('expired_at', '-')}</code>"
157
+ else:
158
+ status_str = "⏳ <b>Pending</b>"
159
+ status_lines.append(f"Amount: <code>{amount}</code><br>"
160
+ f'<a href="{pay_url}">Click here to pay</a><br>'
161
+ f"ID: <code>{payment_id}</code><br>{status_str}")
162
+ await msg.edit("<br><br>".join(status_lines), disable_web_page_preview=True, parse_mode="html")
163
+
164
+ # /extolbal
165
+ @app.on_message(filters.command("extolbal"))
166
+ async def extol_balance_handler(client, message: Message):
167
+ msg = await message.reply_text("πŸ” Fetching Extol balance...")
168
+ resp = await extol_request(message.from_user.id, "/api/balance")
169
+ if not resp.get("ok"):
170
+ return await msg.edit(f"❌ Error: `{resp.get('error')}`")
171
+ balance = resp.get("balance", 0)
172
+ address = resp.get("address", "Unknown")
173
+ await msg.edit(f"πŸ’° Balance: {balance} EXT\n🏷️ **Address: {address}")
174
+
175
+ # /sendextol <to_address> <amount>
176
+ @app.on_message(filters.command("sendextol"))
177
+ async def send_extol_handler(client, message: Message):
178
+ args = message.text.split()
179
+ if len(args) != 3 or not args[2].isdigit() or not args[1].startswith("EXT"):
180
+ await message.reply_text("Usage: /sendextol <to_address> <amount>")
181
+ return
182
+ to_address, amt = args[1], int(args[2])
183
+ if amt <= 0:
184
+ await message.reply_text("❌ Amount must be positive.")
185
+ return
186
+ msg = await message.reply_text("πŸ”„ Sending Extol...")
187
+ resp = await extol_request(
188
+ message.from_user.id,
189
+ "/api/withdraw",
190
+ method="GET",
191
+ params={"amount": amt, "address": to_address},
192
+ )
193
+ if not resp.get("ok"):
194
+ error_msg = resp.get('error') or 'Unknown error (no message from API)'
195
+ code = resp.get('code')
196
+ if code is not None:
197
+ error_msg = f"(code {code}) {error_msg}"
198
+ return await msg.edit(f"❌ Error: {error_msg}")
199
+ link = resp.get("link", "No explorer link.")
200
+ await msg.edit(f"βœ… Sent {amt} EXT to {to_address} \n<a href='{link}'>View Transaction</a>", disable_web_page_preview=True, parse_mode="html")
201
+
202
+ # --- HTTPX helper ---
203
+
204
+ async def extol_request(user_id, path, method="GET", data=None, params=None):
205
+ api_key = await get_user_api_key(user_id)
206
+ if not api_key:
207
+ return {"ok": False, "error": "API key not set. Use /addapi <key> in DM."}
208
+ async with httpx.AsyncClient() as client:
209
+ headers = {"api-key": api_key}
210
+ try:
211
+ if method == "GET":
212
+ r = await client.get(f"{API_BASE_URL}{path}", headers=headers, params=params, timeout=10)
213
+ else:
214
+ r = await client.post(f"{API_BASE_URL}{path}", headers=headers, json=data, timeout=10)
215
+ return r.json()
216
+ except Exception as e:
217
+ return {"ok": False, "error": str(e)}