Вот код
Код: Выделить всё
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove
from telegram.constants import ParseMode
from telegram.ext import Application, CommandHandler, MessageHandler, ConversationHandler, CallbackQueryHandler, filters, ContextTypes, JobQueue
from datetime import datetime, timedelta
import re
import time
# Define VIP levels and thresholds
VIP_THRESHOLDS = {
1: 5000,
2: 20000,
3: 60000,
4: 100000,
5: 300000,
6: 600000,
7: 1000000
}
VIP_PROFITS = {
1: 250,
2: 1000,
3: 3000,
4: 5000,
5: 15000,
6: 30000,
7: 50000
}
user_balances = {}
main_account_balances = {}
user_referrals = {} # {referrer_id: [(referral_name, referred_user_id), ...]}
blocked_users = set() # Store blocked user IDs
blocked_users = set() # Store blocked user IDs
# Task completion function
async def complete_task(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
query = update.callback_query
user_id = query.from_user.id
# Check if the user is blocked
if user_id in blocked_users:
await query.answer()
await query.edit_message_text("Sorry😰, You can not complete this task today. You need to Upgrade your account to the next or Higher VIP level for you to be able accumulating the task. Thank you ")
return
main_balance = main_account_balances.get(user_id, 0)
# Determine VIP level based on the main balance
vip_level = None
for level, threshold in sorted(VIP_THRESHOLDS.items(), reverse=True):
if main_balance >= threshold:
vip_level = level
break
if vip_level:
profit = VIP_PROFITS[vip_level]
user_balances[user_id] = user_balances.get(user_id, 0) + profit
await query.answer()
await query.edit_message_text(f"Task completed🥳! You have earned {profit:,} TZS. Your new balance is {user_balances[user_id]:,} TZS.")
# Give 6% of the profit to the referrer
referrer_id = find_referrer(user_id)
if referrer_id:
referral_bonus = profit * 0.06
user_balances[referrer_id] = user_balances.get(referrer_id, 0) + referral_bonus
await context.bot.send_message(
chat_id=referrer_id,
text=f"💥You received a bonus of {referral_bonus:,.0f} TZS because your referral has completed a task and earned {profit:,} TZS.💥"
)
else:
await query.answer()
await query.edit_message_text("You are not eligible to complete this task.")
def find_referrer(user_id: int) -> int:
for referrer_id, referrals in user_referrals.items():
for referral_name, ref_id in referrals:
if user_id == ref_id:
return referrer_id
return None
# Admin command to list all users with VIP levels from VIP1 to VIP7
async def admin_list(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
if update.message.from_user.id == BOT_OWNER_ID:
vip_users = []
for user_id, main_balance in main_account_balances.items():
vip_level = None
for level, threshold in sorted(VIP_THRESHOLDS.items(), reverse=True):
if main_balance >= threshold:
vip_level = level
break
if vip_level and vip_level >= 1:
user = await context.bot.get_chat(user_id)
user_info = f"{user.first_name} {user.last_name or ''} (VIP{vip_level}, ID: {user_id}
vip_users.append(user_info)
if vip_users:
vip_list = "\n".join(vip_users)
await update.message.reply_text(f"VIP Users:\n\n{vip_list}", parse_mode=ParseMode.HTML)
else:
await update.message.reply_text("No VIP users found.")
else:
await update.message.reply_text("You are not authorized to use this command.")
# Admin command handler
async def admin_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
if update.message.from_user.id == BOT_OWNER_ID:
try:
subcommand = context.args[0]
user_id = int(context.args[1])
if subcommand == 'block':
blocked_users.add(user_id)
await update.message.reply_text(f"User {user_id} has been blocked from completing tasks.")
elif subcommand == 'unblock':
blocked_users.discard(user_id)
await update.message.reply_text(f"User {user_id} has been unblocked from completing tasks.")
else:
await update.message.reply_text("Invalid subcommand. Use /admin block or /admin unblock ")
except (IndexError, ValueError):
await update.message.reply_text("Usage: /admin block or /admin unblock ")
else:
await update.message.reply_text("You are not authorized to use this command.")
# Function to send task messages
async def send_task_message(context: ContextTypes.DEFAULT_TYPE) -> None:
global last_task_time
last_task_time = datetime.now() # Update the timestamp of the last task message
for user_id, main_balance in main_account_balances.items():
# Check if user is at least VIP1
if main_balance >= VIP_THRESHOLDS[1]:
keyboard = [[InlineKeyboardButton("ðŸ˜Complete taskðŸ˜", callback_data='complete_task')]]
reply_markup = InlineKeyboardMarkup(keyboard)
await context.bot.send_message(
chat_id=user_id,
text="Hello there dear, Your task is almost set for completion! kindly press the button below to complete the task and get your money back in your account",
reply_markup=reply_markup
)
# Define stages for the conversation
ASK_AMOUNT, ASK_MOBILE, ASK_OPERATOR, CONFIRM = range(4)
# In-memory user balances for demonstration (should be replaced with a database in production)
user_balances = {}
main_account_balances = {}
user_referrals = {}
def escape_markdown(text: str) -> str:
"""Helper function to escape characters for MarkdownV2."""
escape_chars = r'_*[]()~`>#+-=|{}.!'
return re.sub(f'([{re.escape(escape_chars)}])', r'\\\\1', text)
# Define the invite button handler
async def invite_button(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
user_id = update.message.from_user.id
first_name = update.message.from_user.first_name
last_name = update.message.from_user.last_name or ""
referral_link = f"https://t.me/spotmarketingbot?start={user_id}"
referrals = user_referrals.get(user_id, [])
referral_details = "\n".join(
[f"{referral_name}: {main_account_balances.get(referral_id, 0):,.0f} TZS" for referral_name, referral_id in referrals]
)
total_referral_balance = sum(main_account_balances.get(referral_id, 0) for _, referral_id in referrals)
invite_message = (
f"Hello {first_name} {last_name},\n\n"
"Share the following referral link with your friends to join the bot and get daily commission of (6%) directly in your account, Withdraw anytime you want :\n"
f"{referral_link}\n\n"
f"You have {len(referrals)} referrals:\n{referral_details}\n\n"
f"Total main account balance of your referrals: {total_referral_balance:,.0f} TZS"
)
await update.message.reply_text(invite_message)
# Define the start command handler
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
user_id = update.message.from_user.id
first_name = update.message.from_user.first_name
last_name = update.message.from_user.last_name or ""
referrer_id = context.args[0] if context.args else None
if user_id not in user_balances:
user_balances[user_id] = 1_000_000 if user_id == BOT_OWNER_ID else 500 # Default balance for users and admin
if user_id not in main_account_balances:
main_account_balances[user_id] = 1_000_000 if user_id == BOT_OWNER_ID else 0 # Main account balance for users and admin
# Handle referrals
if referrer_id and referrer_id != user_id:
referrer_id = int(referrer_id)
if referrer_id not in user_referrals:
user_referrals[referrer_id] = []
if user_id not in [ref_id for ref_name, ref_id in user_referrals[referrer_id]]:
user_referrals[referrer_id].append((f"{first_name} {last_name}", user_id))
await context.bot.send_message(
chat_id=referrer_id,
text=f"🎉 {first_name} {last_name} has joined using your referral link! click on the invite button to see the level of your referral"
)
# Notify admin
total_users = len(user_balances)
await context.bot.send_message(
chat_id=BOT_OWNER_ID,
text=f"New user joined: {first_name} {last_name} ({user_id}).\nTotal users: {total_users}"
)
keyboard = [
[KeyboardButton("🦠Main account"), KeyboardButton("💸 Withdraw")],
[KeyboardButton("💰 Deposit"), KeyboardButton("📊 Balance")],
[KeyboardButton("👥 Invite"), KeyboardButton("â„¹ï¸ About")],
[KeyboardButton("â“ Help")]
]
if user_id == BOT_OWNER_ID:
keyboard.append([KeyboardButton("🔧 Admin")])
reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
welcome_message = (
f"Hey {first_name} {last_name}, welcome to Spot-marketing, want to make more money? "
"just start with us and earn passive income daily💥💥💥"
)
if 'has_welcomed' not in context.user_data:
await update.message.reply_text(welcome_message, reply_markup=reply_markup)
context.user_data['has_welcomed'] = True
else:
await update.message.reply_text("Choose an option:", reply_markup=reply_markup)
# Define stages for the conversation
SELECT_VIP_LEVEL, ENTER_USER_ID = range(2)
# Admin command handler
async def admin(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
user_id = update.message.from_user.id
if user_id == BOT_OWNER_ID:
keyboard = [
[InlineKeyboardButton("Change Main Balance", callback_data='change_balance')]
]
reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text("Admin Menu:", reply_markup=reply_markup)
else:
await update.message.reply_text("You are not authorized to access this command.")
# Admin callback handler
async def admin_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
query = update.callback_query
await query.answer()
if query.data == 'change_balance':
keyboard = [
[InlineKeyboardButton("VIP1", callback_data='vip_1'), InlineKeyboardButton("VIP2", callback_data='vip_2')],
[InlineKeyboardButton("VIP3", callback_data='vip_3'), InlineKeyboardButton("VIP4", callback_data='vip_4')],
[InlineKeyboardButton("VIP5", callback_data='vip_5'), InlineKeyboardButton("VIP6", callback_data='vip_6')],
[InlineKeyboardButton("VIP7", callback_data='vip_7')]
]
reply_markup = InlineKeyboardMarkup(keyboard)
await query.edit_message_text("Select VIP Level:", reply_markup=reply_markup)
# VIP selection handler
async def vip_selection(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
query = update.callback_query
await query.answer()
context.user_data['selected_vip'] = query.data.split('_')[1]
await query.edit_message_text(f"Selected VIP{context.user_data['selected_vip']}. Please enter the User ID:")
return ENTER_USER_ID
# Enter user ID handler
async def enter_user_id(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user_id = int(update.message.text)
selected_vip = context.user_data.get('selected_vip')
# Update user's main account balance
if selected_vip:
vip_threshold = VIP_THRESHOLDS[int(selected_vip)]
main_account_balances[user_id] = vip_threshold
await update.message.reply_text(f"User {user_id} has been upgraded to VIP{selected_vip} with balance {vip_threshold:,} TZS.")
# Notify the user
await context.bot.send_message(
chat_id=user_id,
text=f"Your account has been upgraded to VIP{selected_vip} with balance {vip_threshold:,} TZS✅✅✅. Now you can complete task and get more profits once the time is up"
)
return ConversationHandler.END
# Helper function to format timedelta as hrs:min:sec
def format_timedelta(td: timedelta) -> str:
total_seconds = int(td.total_seconds())
hours, remainder = divmod(total_seconds, 3600)
minutes, seconds = divmod(remainder, 60)
return f"{hours:02}:{minutes:02}:{seconds:02}"
# Main account command handler
async def main_account(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
user_id = update.message.from_user.id
balance_tzs = main_account_balances.get(user_id, 0)
now = datetime.now()
next_task_time = last_task_time + TASK_INTERVAL
remaining_time = next_task_time - now
countdown_message = f"Next task available in: {format_timedelta(remaining_time)}🌀"
# Determine VIP level based on the main balance
vip_level = 0
for level, threshold in sorted(VIP_THRESHOLDS.items(), reverse=True):
if balance_tzs >= threshold:
vip_level = level
break
# Generate the VIP levels display
vip_display = "\n".join([f"VIP {i} {'✅' if i == vip_level else ''}" for i in range(8)])
balance_message = (
f"Main Account Balance:[/b]\n" f"{balance_tzs:,.0f} TZS\n\n" f"Your VIP Level:\n" f"{vip_display}\n\n"
f"Your Telegram ID:
Код: Выделить всё
{user_id}
)
await update.message.reply_text(balance_message, parse_mode=ParseMode.HTML)
# Define the deposit command handler
async def deposit(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
keyboard = [
[InlineKeyboardButton("Deposit via Tigo Pesa", callback_data='deposit_tigo')],
[InlineKeyboardButton("Deposit via AirtelMoney", callback_data='deposit_airtel')],
[InlineKeyboardButton("Show VIPs", callback_data='show_vips')]
]
reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text("Choose your deposit method:", reply_markup=reply_markup)
# Handle deposit options
async def handle_deposit_option(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
query = update.callback_query
await query.answer()
deposit_message = ""
if query.data == 'deposit_tigo':
deposit_message = (
"Deposit via Tigo Pesa 🌟\n\n"
"Dial *150*01#\n"
"Choose 5 (Lipa kwa simu)\n"
"Choose 5 (To other Network)\n"
"Choose 3 (Airtel money)\n"
"Enter merchant number as (134 150 06) Name 'FOREX BUSINESS'\n"
"Enter amount\n"
"Enter PIN\n"
"Done\n\n"
"Please send a screenshot of the proof of payment to customer care."
)
elif query.data == 'deposit_airtel':
deposit_message = (
"Deposit via AirtelMoney 🌟\n\n"
"Dial *150*60#\n"
"Choose 5 (Lipa bili)\n"
"Choose 1 (Lipa kwa simu)\n"
"Choose 2 (Lipa kwa voda lipa)\n"
"Enter amount\n"
"Ingiza lipa namba (3528 6848) NAME BYTE-STREAM\n"
"Enter PIN\n"
"Done\n\n"
"Please send a screenshot of the proof of payment to customer care."
)
if deposit_message:
await query.edit_message_text(deposit_message)
# Handler for showing VIP levels and profits
async def show_vips(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
query = update.callback_query
await query.answer()
vip_message = (
"🅠VIP Levels and Daily Profits:\n" "VIP1: 5,000 TZS - Profits: 250 TZS/day\n"
"VIP2: 20,000 TZS - Profits: 1,000 TZS/day\n"
"VIP3: 60,000 TZS - Profits: 3,000 TZS/day\n"
"VIP4: 100,000 TZS - Profits: 5,000 TZS/day\n"
"VIP5: 300,000 TZS - Profits: 15,000 TZS/day\n"
"VIP6: 600,000 TZS - Profits: 30,000 TZS/day\n"
"VIP7: 1,000,000 TZS - Profits: 50,000 TZS/day"
)
await query.edit_message_text(vip_message, parse_mode=ParseMode.HTML)
# Start the withdrawal conversation
async def withdraw(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
first_name = update.message.from_user.first_name
last_name = update.message.from_user.last_name or ""
await update.message.reply_text(f"Do you want to withdraw money now? {first_name} {last_name}, it's free No any charges")
await update.message.reply_text(
"Please enter the amount to withdraw:", reply_markup=ReplyKeyboardRemove(),
parse_mode=ParseMode.HTML
)
return ASK_AMOUNT
MIN_WITHDRAWAL_AMOUNT = 1000
# Ask for the amount to withdraw
async def ask_amount(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
try:
amount = int(update.message.text)
if amount < MIN_WITHDRAWAL_AMOUNT:
await update.message.reply_text(f"The minimum withdrawal amount is {MIN_WITHDRAWAL_AMOUNT} TZS. Please enter a valid amount.")
return ASK_AMOUNT
if amount int:
context.user_data['mobile'] = update.message.text
keyboard = [
[KeyboardButton("Vodacom"), KeyboardButton("Tigo")],
[KeyboardButton("Halotel"), KeyboardButton("Airtel")]
]
reply_markup = ReplyKeyboardMarkup(keyboard, one_time_keyboard=True, resize_keyboard=True)
await update.message.reply_text(
"Please choose your mobile operator:", reply_markup=reply_markup,
parse_mode=ParseMode.HTML
)
return ASK_OPERATOR
# Ask for the mobile operator
async def ask_operator(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
context.user_data['operator'] = update.message.text
keyboard = [
[KeyboardButton("✅ Submit"), KeyboardButton("⌠Cancel")]
]
reply_markup = ReplyKeyboardMarkup(keyboard, one_time_keyboard=True, resize_keyboard=True)
await update.message.reply_text(
"Please press Submit to complete the withdrawal or Cancel to abort:", reply_markup=reply_markup,
parse_mode=ParseMode.HTML
)
return CONFIRM
# Confirm and process the withdrawal
async def confirm(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user_id = update.message.from_user.id
first_name = update.message.from_user.first_name
last_name = update.message.from_user.last_name or ""
text = update.message.text
if text == "✅ Submit":
amount = context.user_data['amount']
mobile = context.user_data['mobile']
operator = context.user_data['operator']
if user_id not in user_balances or user_balances[user_id] < amount:
await update.message.reply_text("Insufficient balance for this withdrawal.")
await start(update, context)
return ConversationHandler.END
# Deduct the amount from user's balance
user_balances[user_id] -= amount
# Send the withdrawal details to the bot owner
await context.bot.send_message(
chat_id=BOT_OWNER_ID,
text=(
f"Withdrawal Request:\n" f"Name: {first_name} {last_name}\n" f"Amount: {amount:,.0f} TSH\n" f"Mobile: {mobile}\n" f"Operator: {operator}"
),
parse_mode=ParseMode.HTML
)
await update.message.reply_text(
f"Withdrawal request submitted successfully. "
f"{amount:,.0f} TSH will be sent to {mobile} via {operator} within 15 minutes.",
parse_mode=ParseMode.HTML
)
else:
await update.message.reply_text("Withdrawal request canceled.")
await start(update, context)
return ConversationHandler.END
# Schedule the job to run every 24 hrs
async def schedule_task_messages(job_queue: JobQueue) -> None:
job_queue.run_repeating(send_task_message, interval=86400, first=0)
async def post_init(app: Application) -> None:
await schedule_task_messages(app.job_queue)
def main() -> None:
application = Application.builder().token(API_TOKEN).post_init(post_init).build()
withdraw_conversation_handler = ConversationHandler(
entry_points=[MessageHandler(filters.Text("💸 Withdraw"), withdraw)],
states={
ASK_AMOUNT: [MessageHandler(filters.TEXT & ~filters.COMMAND, ask_amount)],
ASK_MOBILE: [MessageHandler(filters.TEXT & ~filters.COMMAND, ask_mobile)],
ASK_OPERATOR: [MessageHandler(filters.TEXT & ~filters.COMMAND, ask_operator)],
CONFIRM: [MessageHandler(filters.TEXT & ~filters.COMMAND, confirm)]
},
fallbacks=[]
)
application.add_handler(CommandHandler("start", start))
application.add_handler(CommandHandler("help", help_command))
application.add_handler(MessageHandler(filters.Text("📊 Balance"), balance))
application.add_handler(MessageHandler(filters.Text("🦠Main account"), main_account))
application.add_handler(MessageHandler(filters.Text("💰 Deposit"), deposit))
application.add_handler(MessageHandler(filters.Text("â“ Help"), help_button))
application.add_handler(CallbackQueryHandler(handle_deposit_option, pattern='^deposit_'))
application.add_handler(CallbackQueryHandler(show_vips, pattern='^show_vips$')) # Add this line
application.add_handler(MessageHandler(filters.Text("â„¹ï¸ About"), about_button))
application.add_handler(MessageHandler(filters.Text("👥 Invite"), invite_button))
application.add_handler(CallbackQueryHandler(complete_task, pattern='complete_task'))
application.add_handler(CommandHandler("admin", admin_command))
application.add_handler(CommandHandler("admin_list", admin_list))
application.add_handler(MessageHandler(filters.Text("🔧 Admin"), admin))
application.add_handler(CallbackQueryHandler(admin_callback, pattern='^change_balance$'))
# Add the conversation handler for admin balance change
admin_conv_handler = ConversationHandler(
entry_points=[CallbackQueryHandler(vip_selection, pattern='^vip_')],
states={
ENTER_USER_ID: [MessageHandler(filters.TEXT & ~filters.COMMAND, enter_user_id)]
},
fallbacks=[]
)
application.add_handler(admin_conv_handler)
# Add the conversation handler for withdrawal
application.add_handler(withdraw_conversation_handler)
application.run_polling()
if __name__ == '__main__':
main()
Подробнее здесь: https://stackoverflow.com/questions/787 ... ot-bug-fix