This Python bot manages Litecoin (LTC) payments (with blockchain verification) for a Discord server, featuring SQLite database integration for user balances and transactions, key generation for Product 1 and Product 2 Products, and Product 1/Product 2 loader building capabilities with custom build commands.
Follow these steps to set up your LTC Payment Discord Bot:
pip install discord.py sqlite3 requests aiohttp
bot.db
(auto-initialized by bot).bot.py
and run:
python bot.py
Notes:
$help_bot
.Modules and initial bot configuration with redacted sensitive data.
import discord
from discord.ext import commands
import sqlite3
import time
import random
import requests
import json
import asyncio
import os
import logging
from datetime import datetime, timedelta
import aiohttp
import urllib.parse
# Bot Configuration
YOUR_GUILD_ID = [redacted]
WHITELISTED_ADMIN = [redacted]
TOKEN = "[redacted]"
LTC_ADDRESS = '[redacted]'
Product 2_PATH = r"C:\\Users\\Administrator\\Desktop\\Product 2.exe"
pending_deposits = {}
VALID_TXID_LENGTH = 64
# API Endpoints
COINBASE_API_URL = '[redacted]'
BLOCKCYPHER_API_URL = '[redacted]'
# Discord Bot Setup
intents = discord.Intents.default()
intents.members = True
intents.message_content = True
client = commands.Bot(command_prefix="$", intents=intents)
rgb_color = (0, 0, 0)
hex_color = f'#{rgb_color[0]:02x}{rgb_color[1]:02x}{rgb_color[2]:02x}'
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('bot.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
SQLite database setup and helper functions.
def is_reseller(member):
return discord.utils.get(member.roles, name="reseller") is not None
def init_db():
with sqlite3.connect('bot.db') as conn:
c = conn.cursor()
c.execute('''
CREATE TABLE IF NOT EXISTS users (
user_id TEXT PRIMARY KEY,
balance REAL DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
c.execute('''
CREATE TABLE IF NOT EXISTS transactions (
txid TEXT PRIMARY KEY,
user_id TEXT,
amount_ltc REAL,
amount_usd REAL,
status TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users (user_id)
)
''')
conn.commit()
def get_user_balance(user_id):
with sqlite3.connect('bot.db') as conn:
c = conn.cursor()
c.execute('SELECT balance FROM users WHERE user_id = ?', (str(user_id),))
result = c.fetchone()
return result[0] if result else 0.0
def update_balance(user_id, amount):
try:
with sqlite3.connect('bot.db') as conn:
c = conn.cursor()
c.execute('SELECT balance FROM users WHERE user_id = ?', (str(user_id),))
result = c.fetchone()
if result is not None:
current_balance = result[0]
new_balance = current_balance + amount
c.execute('UPDATE users SET balance = ? WHERE user_id = ?',
(new_balance, str(user_id)))
else:
c.execute('INSERT INTO users (user_id, balance) VALUES (?, ?)',
(str(user_id), amount))
conn.commit()
logger.info(f"Updated balance for user {user_id}: {amount:+.2f}")
return True
except Exception as e:
logger.error(f"Error updating balance for user {user_id}: {e}")
return False
def add_transaction(txid, user_id, amount_ltc, amount_usd, status):
with sqlite3.connect('bot.db') as conn:
c = conn.cursor()
c.execute('''
INSERT INTO transactions (txid, user_id, amount_ltc, amount_usd, status)
VALUES (?, ?, ?, ?, ?)
''', (txid, str(user_id), amount_ltc, amount_usd, status))
conn.commit()
def is_transaction_used(txid):
with sqlite3.connect('bot.db') as conn:
c = conn.cursor()
c.execute('SELECT txid FROM transactions WHERE txid = ?', (txid,))
return c.fetchone() is not None
async def generate_qr_code(address, amount=None):
qr_content = f"litecoin:{address}"
if amount:
qr_content += f"?amount={amount}"
encoded_content = urllib.parse.quote(qr_content)
return f"[redacted]?size=200x200&data={encoded_content}"
async def get_ltc_price():
try:
async with aiohttp.ClientSession() as session:
async with session.get('[redacted]') as response:
if response.status == 200:
data = await response.json()
return float(data['data']['rates']['USD'])
else:
logger.error(f"Failed to get LTC price. Status: {response.status}")
return None
except Exception as e:
logger.error(f"Error getting LTC price: {e}")
return None
async def add_member_roles(guild_id, member_id):
try:
guild = client.get_guild(guild_id)
if guild:
member = await guild.fetch_member(member_id)
if member:
roles_to_add = ["pro","pro v2", "customer"]
for role_name in roles_to_add:
role = discord.utils.get(guild.roles, name=role_name)
if role and role not in member.roles:
await member.add_roles(role)
logger.info(f"Added {role_name} role to {member.name}")
except Exception as e:
logger.error(f"Error adding roles: {e}")
def format_ltc(amount):
"""Format LTC amount to max 8 decimal places without trailing zeros"""
return f"{amount:.8f}".rstrip('0').rstrip('.')
Core event handlers and LTC payment verification logic.
@client.event
async def on_ready():
init_db()
logger.info(f"Bot is ready as {client.user.name}")
client.loop.create_task(cleanup_old_transactions())
client.loop.create_task(cleanup_pending_deposits())
await client.change_presence(
status=discord.Status.online,
activity=discord.Game(name="$help_bot")
)
@client.command(name='checkbalance')
async def check_balance_admin(ctx, user_id: str):
if ctx.author.id != WHITELISTED_ADMIN:
return
try:
with sqlite3.connect('bot.db') as conn:
c = conn.cursor()
c.execute('''
SELECT balance, created_at
FROM users
WHERE user_id = ?
''', (user_id,))
result = c.fetchone()
if result:
balance, created_at = result
embed = discord.Embed(
title="Balance Check",
description=f"User ID: {user_id}\nBalance: ${balance:.2f}\nAccount Created: {created_at}",
color=int(hex_color[1:], 16)
)
await ctx.reply(embed=embed)
else:
await ctx.reply("User not found in database.")
except Exception as e:
logger.error(f"Error checking balance: {e}")
await ctx.reply("Error checking balance.")
async def verify_ltc_payment(txid, user_id):
logger.info(f"Starting verification for TXID {txid}")
if len(txid) != VALID_TXID_LENGTH:
logger.warning(f"Invalid TXID length: {len(txid)}")
return False, 0, 0
if is_transaction_used(txid):
logger.warning(f"Transaction {txid} already used")
return False, 0, 0
for attempt in range(10):
try:
async with aiohttp.ClientSession() as session:
logger.info(f"Fetching transaction data from BlockCypher for {txid} (Attempt {attempt + 1}/10)")
async with session.get('[redacted]' + txid) as response:
logger.info(f"BlockCypher response status: {response.status}")
if response.status == 200:
data = await response.json()
logger.info(f"Transaction data received: {data}")
if data.get('confirmations', 0) >= 1:
received_amount = sum(
output['value'] for output in data['outputs']
if output.get('addresses', [None])[0] == '[redacted]'
)
logger.info(f"Received amount in satoshis: {received_amount}")
received_ltc = received_amount / 1e8
received_ltc_formatted = format_ltc(received_ltc)
logger.info(f"Converted amount: {received_ltc_formatted} LTC")
ltc_price = await get_ltc_price()
if ltc_price is None:
logger.error("Failed to get LTC price")
if attempt == 9:
return False, 0, 0
continue
logger.info(f"Current LTC price: ${ltc_price}")
usd_value = round(received_ltc * ltc_price, 2)
logger.info(f"USD value: ${usd_value}")
try:
guild = client.get_guild(YOUR_GUILD_ID)
if guild:
member = await guild.fetch_member(int(user_id))
if member:
is_user_reseller = is_reseller(member)
min_deposit = 100 if is_user_reseller else 0
if is_user_reseller and usd_value < min_deposit:
logger.warning(f"Reseller deposit below minimum: ${usd_value:.2f}")
return False, 0, 0
except Exception as e:
logger.warning(f"Could not verify member status: {e}")
add_transaction(txid, user_id, float(received_ltc_formatted), usd_value, 'completed')
logger.info(f"Transaction recorded successfully")
return True, float(received_ltc_formatted), usd_value
logger.info(f"Transaction {txid} not confirmed yet (Attempt {attempt + 1}/10)")
if attempt < 9:
await asyncio.sleep(60)
continue
return False, 0, 0
elif response.status == 404:
logger.info(f"Transaction not found yet (Attempt {attempt + 1}/10)")
if attempt < 9:
await asyncio.sleep(60)
continue
return False, 0, 0
else:
logger.error(f"Failed to verify transaction. Status: {response.status}")
if attempt < 9:
await asyncio.sleep(60)
continue
return False, 0, 0
except Exception as e:
logger.error(f"Error verifying transaction: {e}")
if attempt < 9:
await asyncio.sleep(60)
continue
return False, 0, 0
async def is_reseller_safe(user_id):
try:
guild = client.get_guild(YOUR_GUILD_ID)
if guild:
member = await guild.fetch_member(int(user_id))
if member:
return discord.utils.get(member.roles, name="reseller") is not None
except Exception as e:
logger.warning(f"Could not verify reseller status: {e}")
return False
async def generate_qr_code_with_amount(address, ltc_price, is_reseller=False):
if is_reseller:
ltc_amount = 100 / ltc_price
qr_content = f"litecoin:{address}?amount={format_ltc(ltc_amount)}"
else:
qr_content = f"litecoin:{address}"
encoded_content = urllib.parse.quote(qr_content)
return f"[redacted]?size=200x200&data={encoded_content}"
Deposit command and message event handler for payment processing.
@client.command(name='deposit')
@commands.guild_only()
async def deposit(ctx):
is_user_reseller = await is_reseller_safe(ctx.author.id)
ltc_price = await get_ltc_price()
if ltc_price is None:
await ctx.author.send("Error getting LTC price. Please try again later.")
return
min_deposit = 100 if is_user_reseller else 0
if is_user_reseller:
await ctx.reply(f"As a reseller, minimum deposit is ${min_deposit:.2f}. Check your DMs for deposit information!")
else:
await ctx.reply("Check your DMs for deposit information!")
qr_code_url = await generate_qr_code_with_amount('[redacted]', ltc_price, is_user_reseller)
description = "Send any amount of LTC to top up your balance.\n"
if is_user_reseller:
min_ltc = min_deposit / ltc_price
description = f"Minimum deposit: ${min_deposit:.2f} (approximately {format_ltc(min_ltc)} LTC)\n"
description += "Send your transaction ID (txid) in this DM after making the payment"
embed = discord.Embed(
title="LTC Deposit Information",
description=description,
color=int(hex_color[1:], 16)
)
embed.add_field(name="LTC Address", value=f"`[redacted]`")
if is_user_reseller:
min_ltc = min_deposit / ltc_price
embed.add_field(name="Recommended Amount", value=f"`{format_ltc(min_ltc)} LTC`", inline=False)
embed.set_thumbnail(url="[redacted]")
embed.set_image(url=qr_code_url)
await ctx.author.send(embed=embed)
pending_deposits[ctx.author.id] = True
@client.event
async def on_message(message):
if message.author == client.user:
return
if isinstance(message.channel, discord.DMChannel):
user_id = message.author.id
if user_id in pending_deposits:
if message.content.startswith('0x') or len(message.content) == 64:
txid = message.content.strip()
status_message = await message.channel.send("Starting transaction verification... This will take up to 10 minutes.")
try:
success, ltc_amount, usd_value = await verify_ltc_payment(txid, user_id)
is_user_reseller = await is_reseller_safe(user_id)
min_deposit = 100 if is_user_reseller else 0
if success:
update_balance(user_id, usd_value)
current_balance = get_user_balance(user_id)
embed = discord.Embed(
title="Deposit Successful",
description=f"Successfully deposited {format_ltc(ltc_amount)} LTC (${usd_value:.2f})\n"
f"New balance: ${current_balance:.2f}",
color=int(hex_color[1:], 16)
)
embed.set_thumbnail(url="[redacted]")
await message.channel.send(embed=embed)
try:
await add_member_roles(YOUR_GUILD_ID, user_id)
except Exception as e:
logger.warning(f"Could not add roles to user {user_id}: {e}")
else:
if is_user_reseller and usd_value < min_deposit:
await message.channel.send(f"Deposit failed: Amount ${usd_value:.2f} is below the reseller minimum of ${min_deposit:.2f}")
else:
await message.channel.send("Payment verification failed. Please ensure your transaction is confirmed and try again with $deposit")
except Exception as e:
logger.error(f"Error processing payment: {e}")
await message.channel.send("An error occurred while processing your payment. Please try again or contact support.")
del pending_deposits[user_id]
else:
await message.channel.send("Invalid transaction ID format. Please send a valid transaction ID or use $deposit to start over.")
await client.process_commands(message)
Commands for viewing transactions and checking balances.
@client.command(name='transactions')
async def view_transactions(ctx, user_id: str):
if ctx.author.id != WHITELISTED_ADMIN:
return
with sqlite3.connect('bot.db') as conn:
c = conn.cursor()
c.execute('''
SELECT created_at, amount_ltc, amount_usd, txid, status
FROM transactions
WHERE user_id = ?
ORDER BY created_at DESC
LIMIT 10
''', (user_id,))
transactions = c.fetchall()
if not transactions:
await ctx.reply("No transactions found for this user.")
return
embed = discord.Embed(
title=f"Transaction History for {user_id}",
color=int(hex_color[1:], 16)
)
for tx in transactions:
created_at, amount_ltc, amount_usd, txid, status = tx
embed.add_field(
name=f"Transaction {created_at}",
value=f"LTC: {format_ltc(amount_ltc)}\nUSD: ${amount_usd:.2f}\nStatus: {status}\nTXID: `{txid}`",
inline=False
)
embed.set_thumbnail(url="[redacted]")
await ctx.reply(embed=embed)
async def cleanup_pending_deposits():
while True:
try:
current_time = datetime.utcnow()
for user_id in list(pending_deposits.keys()):
del pending_deposits[user_id]
except Exception as e:
logger.error(f"Error cleaning up pending deposits: {e}")
await asyncio.sleep(3600)
@client.command(name='balance')
async def check_balance(ctx):
balance = get_user_balance(ctx.author.id)
embed = discord.Embed(
title="Balance",
description=f"Your current balance: ${balance:.2f}",
color=int(hex_color[1:], 16)
)
embed.set_thumbnail(url="[redacted]")
await ctx.reply(embed=embed)
Commands for generating Product 1 and Product 2 keys.
@client.command(name='help_bot')
async def help(ctx):
embed = discord.Embed(
title="Help Menu",
description="Available commands:",
color=int(hex_color[1:], 16)
)
embed.add_field(name="$deposit", value="Get LTC deposit information", inline=False)
embed.add_field(name="$balance", value="Check your current balance", inline=False)
embed.add_field(name="$generate_key_month ", value="Generate a month key for Product 1 ($50)", inline=False)
embed.add_field(name="$generate_key_week", value="Generate a week key for Product 1 ($25)", inline=False)
embed.add_field(name="$generate_key_Product 2_month ", value="Generate a month key for Product 2 ($30)", inline=False)
embed.add_field(name="$generate_key_Product 2_week ", value="Generate a week key for Product 2 ($15)", inline=False)
embed.add_field(name="$generate_key_Product 2_day ", value="Generate a month key for Product 2 ($5)", inline=False)
embed.add_field(name="$build", value="Build personal Product 1 loader", inline=False)
embed.add_field(name="?build", value="Build personal Product 2 loader", inline=False)
embed.add_field(name="$prices", value="View Product prices", inline=False)
embed.set_thumbnail(url="[redacted]")
await ctx.reply(embed=embed)
@client.command(name='generate_key_month')
@commands.guild_only()
async def generate_key_month(ctx, amount: int = 1):
is_user_reseller = is_reseller(ctx.author)
price = 25.0*amount if is_user_reseller else 50.0*amount
balance = get_user_balance(ctx.author.id)
if balance < price:
await ctx.reply(f"Insufficient balance. You need ${price:.2f}, but have ${balance:.2f}")
return
api_url = "[redacted]"
try:
keys = []
response = requests.get(api_url)
if response.status_code == 200:
for _ in range(amount):
keys.append(response.text.strip())
else:
await ctx.reply("Error generating keys. Please try again later.")
return
update_balance(ctx.author.id, -price)
embed = discord.Embed(
title="Keys Generated",
description=f"Successfully generated {amount} monthly {'keys' if amount > 1 else 'key'}.\nCheck your DMs for the {'keys' if amount > 1 else 'key'}.",
color=int(hex_color[1:], 16)
)
embed.set_thumbnail(url="[redacted]")
await ctx.reply(embed=embed)
keys_message = "\n".join([f"Monthly key {i+1}: `{key}`" for i, key in enumerate(keys)])
await ctx.author.send(f"{keys_message}\nNew balance: ${get_user_balance(ctx.author.id):.2f}")
except Exception as e:
logger.error(f"Error generating key: {e}")
await ctx.reply("Error generating keys. Please try again later.")
@client.command(name='generate_key_week')
@commands.guild_only()
async def generate_key_week(ctx):
is_user_reseller = is_reseller(ctx.author)
price = 25.0 if is_user_reseller else 25.0
num_keys = 2 if is_user_reseller else 1
balance = get_user_balance(ctx.author.id)
if balance < price:
await ctx.reply(f"Insufficient balance. You need ${price:.2f}, but have ${balance:.2f}")
return
api_url = "[redacted]"
try:
keys = []
for _ in range(num_keys):
response = requests.get(api_url)
if response.status_code == 200:
keys.append(response.text.strip())
else:
await ctx.reply("Error generating keys. Please try again later.")
return
update_balance(ctx.author.id, -price)
embed = discord.Embed(
title="Keys Generated",
description=f"Successfully generated {'2 weekly keys' if num_keys == 2 else 'weekly key'}.\nCheck your DMs for the {'keys' if num_keys == 2 else 'key'}.",
color=int(hex_color[1:], 16)
)
embed.set_thumbnail(url="[redacted]")
await ctx.reply(embed=embed)
keys_message = "\n".join([f"Weekly key {i+1}: `{key}`" for i, key in enumerate(keys)])
await ctx.author.send(f"{keys_message}\nNew balance: ${get_user_balance(ctx.author.id):.2f}")
except Exception as e:
logger.error(f"Error generating key: {e}")
await ctx.reply("Error generating keys. Please try again later.")
@client.command(name='generate_key_Product 2_day')
@commands.guild_only()
async def generate_key_Product 2_day(ctx, amount: int = 1):
is_user_reseller = is_reseller(ctx.author)
price = 2.5*amount if is_user_reseller else 5.0*amount
balance = get_user_balance(ctx.author.id)
if balance < price:
await ctx.reply(f"Insufficient balance. You need ${price:.2f}, but have ${balance:.2f}")
return
api_url = "[redacted]"
try:
keys = []
response = requests.get(api_url)
if response.status_code == 200:
for _ in range(amount):
keys.append(response.text.strip())
else:
await ctx.reply("Error generating keys. Please try again later.")
return
update_balance(ctx.author.id, -price)
embed = discord.Embed(
title="Keys Generated",
description=f"Successfully generated {amount} daily {'keys' if amount > 1 else 'key'}.\nCheck your DMs for the {'keys' if amount > 1 else 'key'}.",
color=int(hex_color[1:], 16)
)
embed.set_thumbnail(url="[redacted]")
await ctx.reply(embed=embed)
keys_message = "\n".join([f"Daily key {i+1}: `{key}`" for i, key in enumerate(keys)])
await ctx.author.send(f"{keys_message}\nNew balance: ${get_user_balance(ctx.author.id):.2f}")
await ctx.author.send(file=discord.File(Product 2_PATH))
except Exception as e:
logger.error(f"Error generating key: {e}")
await ctx.reply("Error generating keys. Please try again later.")
@client.command(name='generate_key_Product 2_week')
@commands.guild_only()
async def generate_key_Product 2_week(ctx, amount: int = 1):
is_user_reseller = is_reseller(ctx.author)
price = 7.5*amount if is_user_reseller else 15.0*amount
balance = get_user_balance(ctx.author.id)
if balance < price:
await ctx.reply(f"Insufficient balance. You need ${price:.2f}, but have ${balance:.2f}")
return
api_url = "[redacted]"
try:
keys = []
response = requests.get(api_url)
if response.status_code == 200:
for _ in range(amount):
keys.append(response.text.strip())
else:
await ctx.reply("Error generating keys. Please try again later.")
return
update_balance(ctx.author.id, -price)
embed = discord.Embed(
title="Keys Generated",
description=f"Successfully generated {amount} weekly {'keys' if amount > 1 else 'key'}.\nCheck your DMs for the {'keys' if amount > 1 else 'key'}.",
color=int(hex_color[1:], 16)
)
embed.set_thumbnail(url="[redacted]")
await ctx.reply(embed=embed)
keys_message = "\n".join([f"Weekly key {i+1}: `{key}`" for i, key in enumerate(keys)])
await ctx.author.send(f"{keys_message}\nNew balance: ${get_user_balance(ctx.author.id):.2f}")
await ctx.author.send(file=discord.File(Product 2_PATH))
except Exception as e:
logger.error(f"Error generating key: {e}")
await ctx.reply("Error generating keys. Please try again later.")
@client.command(name='generate_key_Product 2_month')
@commands.guild_only()
async def generate_key_Product 2_month(ctx, amount: int = 1):
is_user_reseller = is_reseller(ctx.author)
price = 15*amount if is_user_reseller else 30.0*amount
balance = get_user_balance(ctx.author.id)
if balance < price:
await ctx.reply(f"Insufficient balance. You need ${price:.2f}, but have ${balance:.2f}")
return
api_url = "[redacted]"
try:
keys = []
response = requests.get(api_url)
if response.status_code == 200:
for _ in range(amount):
keys.append(response.text.strip())
else:
await ctx.reply("Error generating keys. Please try again later.")
return
update_balance(ctx.author.id, -price)
embed = discord.Embed(
title="Keys Generated",
description=f"Successfully generated {amount} monthly {'keys' if amount > 1 else 'key'}.\nCheck your DMs for the {'keys' if amount > 1 else 'key'}.",
color=int(hex_color[1:], 16)
)
embed.set_thumbnail(url="[redacted]")
await ctx.reply(embed=embed)
keys_message = "\n".join([f"Monthly key {i+1}: `{key}`" for i, key in enumerate(keys)])
await ctx.author.send(f"{keys_message}\nNew balance: ${get_user_balance(ctx.author.id):.2f}")
await ctx.author.send(file=discord.File(Product 2_PATH))
except Exception as e:
logger.error(f"Error generating key: {e}")
await ctx.reply("Error generating keys. Please try again later.")
Pricing, admin commands, and system utilities.
@client.command(name='prices')
async def prices(ctx):
is_user_reseller = is_reseller(ctx.author)
embed = discord.Embed(
title="Product Prices",
description="Current prices for our Products:",
color=int(hex_color[1:], 16)
)
if is_user_reseller:
embed.add_field(name="Monthly Key Product 1", value="$25.00", inline=False)
embed.add_field(name="Weekly Keys Product 1", value="$25.00 (2 keys)", inline=False)
embed.add_field(name="Monthly Key Product 2", value="$15.00", inline=False)
embed.add_field(name="Weekly Key Product 2", value="$7.5.00", inline=False)
embed.add_field(name="Daily Key Product 2", value="$2.50", inline=False)
embed.add_field(name="Minimum Deposit", value="$100.00", inline=False)
else:
embed.add_field(name="Monthly Key Product 1", value="$50.00", inline=False)
embed.add_field(name="Weekly Key Product 1", value="$25.00", inline=False)
embed.add_field(name="Monthly Key Product 2", value="$30.00", inline=False)
embed.add_field(name="Weekly Key Product 2", value="$15.00", inline=False)
embed.add_field(name="Daily Key Product 2", value="$5.00", inline=False)
embed.set_thumbnail(url="[redacted]")
await ctx.reply(embed=embed)
@client.command(name='admin')
async def admin_menu(ctx):
if ctx.author.id != WHITELISTED_ADMIN:
return
embed = discord.Embed(
title="Admin Menu",
description="Available admin commands:",
color=int(hex_color[1:], 16)
)
embed.add_field(name="$transactions ", value="View user's transactions", inline=False)
embed.add_field(name="$setbalance ", value="Set user's balance", inline=False)
embed.set_thumbnail(url="[redacted]")
await ctx.reply(embed=embed)
@client.command(name='setbalance')
async def set_balance(ctx, user_id: str, amount: float):
if ctx.author.id != WHITELISTED_ADMIN:
return
try:
with sqlite3.connect('bot.db') as conn:
c = conn.cursor()
c.execute('''
INSERT INTO users (user_id, balance)
VALUES (?, ?)
ON CONFLICT(user_id)
DO UPDATE SET balance = ?
''', (user_id, amount, amount))
conn.commit()
embed = discord.Embed(
title="Balance Updated",
description=f"Set balance for user {user_id} to ${amount:.2f}",
color=int(hex_color[1:], 16)
)
embed.set_thumbnail(url="[redacted]")
await ctx.reply(embed=embed)
except Exception as e:
logger.error(f"Error setting balance: {e}")
await ctx.reply("Error updating balance.")
@client.command(name='reset')
async def reset(ctx, key=None):
pro_role = discord.utils.get(ctx.author.roles, name="pro")
if pro_role:
if key is not None:
await ctx.message.delete()
await ctx.send("Resetting...")
api_url = f"[redacted]&user={key}"
response = requests.get(api_url)
if response.status_code == 200:
await ctx.send(f"Successfully reset key for {ctx.author.mention}.")
else:
await ctx.send("Failed to reset key. Please try again later.")
else:
await ctx.reply("Please provide the key to reset. Usage: `$reset `")
else:
await ctx.reply("You do not have access to this command.")
@client.command(name='adminhelp')
async def admin_help(ctx):
if ctx.author.id != WHITELISTED_ADMIN:
return
embed = discord.Embed(
title="Admin Help",
description="Detailed admin command information:",
color=int(hex_color[1:], 16)
)
commands = {
"$transactions ": "View last 10 transactions for a user",
"$setbalance ": "Set a user's balance to specific amount",
"$adminhelp": "Show this help message",
"$stats": "Show system statistics"
}
for cmd, desc in commands.items():
embed.add_field(name=cmd, value=desc, inline=False)
embed.set_thumbnail(url="[redacted]")
await ctx.reply(embed=embed)
@client.command(name='stats')
async def show_stats(ctx):
if ctx.author.id != WHITELISTED_ADMIN:
return
try:
with sqlite3.connect('bot.db') as conn:
c = conn.cursor()
c.execute('SELECT COUNT(*) FROM users')
total_users = c.fetchone()[0]
c.execute('SELECT COUNT(*) FROM transactions')
total_transactions = c.fetchone()[0]
c.execute('SELECT SUM(amount_usd) FROM transactions WHERE status = "completed"')
total_volume = c.fetchone()[0] or 0
c.execute('''
SELECT SUM(amount_usd)
FROM transactions
WHERE status = "completed"
AND date(created_at) = date("now")
''')
today_volume = c.fetchone()[0] or 0
embed = discord.Embed(
title="System Statistics",
color=int(hex_color[1:], 16)
)
stats = {
"Total Users": total_users,
"Total Transactions": total_transactions,
"Total Volume": f"${total_volume:.2f}",
"Today's Volume": f"${today_volume:.2f}"
}
for name, value in stats.items():
embed.add_field(name=name, value=value, inline=True)
embed.set_thumbnail(url="[redacted]")
await ctx.reply(embed=embed)
except Exception as e:
logger.error(f"Error getting stats: {e}")
await ctx.reply("Error fetching statistics.")
async def cleanup_old_transactions():
while True:
try:
with sqlite3.connect('bot.db') as conn:
c = conn.cursor()
c.execute('''
DELETE FROM transactions
WHERE status != "completed"
AND datetime(created_at) < datetime("now", "-24 hours")
''')
conn.commit()
except Exception as e:
logger.error(f"Error cleaning up transactions: {e}")
await asyncio.sleep(3600)
Error handling and welcome message for new members.
@client.event
async def on_command_error(ctx, error):
if isinstance(error, commands.errors.CommandNotFound):
return
error_message = "An error occurred while processing your command."
if isinstance(error, commands.errors.MissingRequiredArgument):
error_message = f"Missing required argument: {error.param.name}"
elif isinstance(error, commands.errors.BadArgument):
error_message = f"Invalid argument provided: {str(error)}"
embed = discord.Embed(
title="Error",
description=error_message,
color=discord.Color.red()
)
await ctx.reply(embed=embed)
logger.error(f"Command error in {ctx.command}: {error}")
@client.event
async def on_member_join(member):
try:
loader_channel = client.get_channel([redacted])
embed = discord.Embed(
title="Welcome to MizuTools!",
description=f"Thank you for joining our server! Please use all commands in {loader_channel.mention}",
color=int(hex_color[1:], 16)
)
info = [
"💰 Use `$deposit` to deposit money to buy keys",
"🔑 After depositing, use `$generate_key_month` to buy a key (1 month = $50)",
"💳 Need other payment methods? DM lucas!",
"🔧 Use `$build` for personal Product 1 loader",
"💻 Use `?build` for personal Product 2 loader",
"\n**Additional Info:**",
"• All Product 2 uses WebGUI",
"• Access the interface via the link shown in loader after login"
]
embed.add_field(
name="Getting Started",
value="\n".join(info),
inline=False
)
embed.set_thumbnail(url="[redacted]")
await member.send(embed=embed)
logger.info(f"Sent welcome DM to new member {member.id}")
except Exception as e:
logger.error(f"Error sending welcome DM to {member.id}: {e}")
Product 1 loader building with cooldown and queue system.
import subprocess
import shutil
import datetime
MAIN_CPP_PATH = '[redacted]'
SOLUTION_FILE_PATH = '[redacted]'
BUILD_DIRECTORY = '[redacted]'
VCVARSALL_PATH = '[redacted]'
VM_PROTECT_COMMAND = '[redacted]'
OUTPUT_FILE_PATH = '[redacted]'
PROTECTED_FILE_PATH = '[redacted]'
COOLDOWN_FILE = '[redacted]'
BASE_OUTPUT_DIR = '[redacted]'
queue = []
try:
if os.path.exists(COOLDOWN_FILE) and os.path.getsize(COOLDOWN_FILE) > 0:
with open(COOLDOWN_FILE, 'r') as file:
cooldown_data = json.load(file)
else:
cooldown_data = {}
except json.JSONDecodeError:
cooldown_data = {}
def save_cooldown_data():
with open(COOLDOWN_FILE, 'w') as file:
json.dump(cooldown_data, file)
def update_main_cpp(file_path, username):
with open(file_path, 'r') as file:
content = file.read()
current_time = datetime.datetime.now()
build_time = f"Built for {username} at: {current_time.strftime('%Y-%m-%d %H:%M:%S')} GMT +8"
content = content.replace('BUILD_TIME_PLACEHOLDER', build_time)
with open(file_path, 'w') as file:
file.write(content)
return build_time
def revert_main_cpp(file_path, build_time):
try:
with open(file_path, 'r') as file:
content = file.read()
content = content.replace(build_time, 'BUILD_TIME_PLACEHOLDER')
with open(file_path, 'w') as file:
file.write(content)
except Exception as e:
logger.error(f"Error reverting main.cpp: {e}")
raise
async def process_queue():
while queue:
ctx = queue[0]
user_id = str(ctx.author.id)
username = str(ctx.author)
current_time = datetime.datetime.now()
if user_id == "[redacted]":
pass
else:
if user_id in cooldown_data:
last_execution_time = datetime.datetime.strptime(cooldown_data[user_id], "%Y-%m-%dT%H:%M:%S.%f")
time_since_last_execution = current_time - last_execution_time
if time_since_last_execution < datetime.timedelta(weeks=1):
time_remaining = datetime.timedelta(weeks=1) - time_since_last_execution
await ctx.send(f'You can make a new loader in {time_remaining}.')
queue.pop(0)
continue
try:
await ctx.send(f"Building loader for {username}...")
build_time = update_main_cpp(MAIN_CPP_PATH, username)
os.makedirs(BUILD_DIRECTORY, exist_ok=True)
os.chdir(BUILD_DIRECTORY)
vcvars_command = f'call "[redacted]" x64 && msbuild "[redacted]" /p:Configuration=Release'
process = await asyncio.create_subprocess_shell(vcvars_command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
stdout, stderr = await process.communicate()
if process.returncode == 0:
vm_protect_command = f'[redacted] "[redacted]" -pf "[redacted]"'
vm_protect_process = await asyncio.create_subprocess_shell(vm_protect_command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
vm_protect_stdout, vm_protect_stderr = await vm_protect_process.communicate()
if os.path.exists(OUTPUT_FILE_PATH):
user_dir = os.path.join(BASE_OUTPUT_DIR, username)
os.makedirs(user_dir, exist_ok=True)
user_file_path = os.path.join(user_dir, 'angel.exe')
shutil.copy2(OUTPUT_FILE_PATH, user_file_path)
await ctx.author.send(file=discord.File(user_file_path))
await ctx.send(f'Compilation for {username} successful! Check DM!')
revert_main_cpp(MAIN_CPP_PATH, build_time)
cooldown_data[user_id] = current_time.isoformat()
save_cooldown_data()
else:
await ctx.send(f'An error occurred during VMProtect processing: {vm_protect_stderr.decode()}')
else:
revert_main_cpp(MAIN_CPP_PATH, build_time)
await ctx.send(f'Build failed: {stderr.decode()}')
except Exception as e:
logger.error(f"Error processing build: {e}")
await ctx.send(f'An error occurred: {str(e)}')
queue.pop(0)
await asyncio.sleep(1)
@client.command(name='build')
@commands.guild_only()
async def build_solution(ctx):
if (ctx.channel.id == [redacted]) or (ctx.channel.id == [redacted]):
pass
else:
await ctx.send('You cannot use this command in this channel!')
return
pro_role = discord.utils.get(ctx.author.roles, name="pro")
if not pro_role:
await ctx.reply("You need the 'pro' role to use this command.")
return
user_id = str(ctx.author.id)
username = str(ctx.author)
if user_id in [str(user.author.id) for user in queue]:
await ctx.send(f'{username} is already in the queue. Please wait for your turn.')
else:
queue.append(ctx)
await ctx.send(f'{username} has been added to the queue. Please wait for your turn.')
if len(queue) == 1:
await process_queue()
if __name__ == "__main__":
client.run(TOKEN)