Thanks to visit codestin.com
Credit goes to pastebin.com

Vyvyndra

Untitled

May 12th, 2025 (edited)
26
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 25.07 KB | None | 0 0
  1. import logging
  2. from typing import Dict, List, Optional, Tuple
  3. from dataclasses import dataclass
  4. from datetime import datetime, timedelta
  5. import pytz
  6. from threading import Timer
  7. import random
  8.  
  9. from telegram import Update, ChatMember
  10. from telegram.ext import (
  11.     Updater,
  12.     CommandHandler,
  13.     MessageHandler,
  14.     Filters,
  15.     CallbackContext,
  16.     ConversationHandler,
  17. )
  18.  
  19. # Настройка логгирования
  20. logging.basicConfig(
  21.     format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
  22.     level=logging.INFO
  23. )
  24. logger = logging.getLogger(name)
  25.  
  26. # Состояния для ConversationHandler
  27. CURRENCY_NAME, CURRENCY_EMOJI = range(2)
  28.  
  29. # Структуры данных
  30. @dataclass
  31. class Currency:
  32.     name: str
  33.     emoji: str
  34.     daily_reward: Optional[int] = None
  35.     chat_reward: Optional[int] = None
  36.  
  37. class GroupData:
  38.     def init(self):
  39.         self.currencies: Dict[str, Currency] = {}  # name -> Currency
  40.         self.user_balances: Dict[int, Dict[str, int]] = {}  # user_id -> {currency_name -> amount}
  41.  
  42. # Глобальные хранилища данных
  43. groups: Dict[int, GroupData] = {}
  44. last_daily_rewards: Dict[int, datetime] = {}  # chat_id -> last reward time
  45. user_last_message: Dict[int, Dict[int, datetime]] = {}  # chat_id -> user_id -> last message time
  46.  
  47. def get_group_data(chat_id: int) -> GroupData:
  48.     if chat_id not in groups:
  49.         groups[chat_id] = GroupData()
  50.     return groups[chat_id]
  51.  
  52. # Проверка на администратора
  53. def is_admin(update: Update) -> bool:
  54.     if not update.effective_chat or update.effective_chat.type == 'private':
  55.         return False
  56.    
  57.     user_id = update.effective_user.id
  58.     chat_id = update.effective_chat.id
  59.    
  60.     try:
  61.         member = update.effective_chat.get_member(user_id)
  62.         return member.status in ['creator', 'administrator']
  63.     except Exception as e:
  64.         logger.error(f"Error checking admin status: {e}")
  65.         return False
  66.  
  67. # ====================
  68. # Команды администраторов
  69. # ====================
  70.  
  71. def start_currency_creation(update: Update, context: CallbackContext) -> int:
  72.     if not is_admin(update):
  73.         update.message.reply_text("Только администраторы могут создавать валюты.")
  74.         return ConversationHandler.END
  75.    
  76.     update.message.reply_text(
  77.         "Введите название новой валюты (одним словом без пробелов):"
  78.     )
  79.     return CURRENCY_NAME
  80.  
  81. def process_currency_name(update: Update, context: CallbackContext) -> int:
  82.     currency_name = update.message.text.strip()
  83.     if ' ' in currency_name:
  84.         update.message.reply_text("Название валюты не должно содержать пробелов. Попробуйте еще раз:")
  85.         return CURRENCY_NAME
  86.    
  87.     context.user_data['new_currency_name'] = currency_name
  88.    
  89.     update.message.reply_text(
  90.         f"Введите смайлик для валюты {currency_name} (например, 🪙):"
  91.     )
  92.     return CURRENCY_EMOJI
  93.  
  94. def process_currency_emoji(update: Update, context: CallbackContext) -> int:
  95.     emoji = update.message.text.strip()
  96.     currency_name = context.user_data['new_currency_name']
  97.     chat_id = update.effective_chat.id
  98.    
  99.     group_data = get_group_data(chat_id)
  100.    
  101.     if currency_name in group_data.currencies:
  102.         update.message.reply_text("Валюта с таким названием уже существует!")
  103.         return ConversationHandler.END
  104.    
  105.     group_data.currencies[currency_name] = Currency(name=currency_name, emoji=emoji)
  106.    
  107.     update.message.reply_text(
  108.         f"Валюта {currency_name} {emoji} успешно создана!\n"
  109.         f"Теперь вы можете настроить:\n"
  110.         f"/setdaily {currency_name} [количество] - ежедневные награды\n"
  111.         f"/setchatreward {currency_name} [количество] - награды за сообщения"
  112.     )
  113.    
  114.     return ConversationHandler.END
  115.  
  116. def cancel_creation(update: Update, context: CallbackContext) -> int:
  117.     update.message.reply_text("Создание валюты отменено.")
  118.     return ConversationHandler.END
  119. def set_daily_reward(update: Update, context: CallbackContext):
  120.     if not is_admin(update):
  121.         update.message.reply_text("Только администраторы могут настраивать ежедневные награды.")
  122.         return
  123.    
  124.     if len(context.args) != 2:
  125.         update.message.reply_text(
  126.             "Использование: /setdaily [название валюты] [количество]\n"
  127.             "Используйте 0 чтобы отключить ежедневные награды."
  128.         )
  129.         return
  130.    
  131.     currency_name, amount_str = context.args
  132.     try:
  133.         amount = int(amount_str)
  134.     except ValueError:
  135.         update.message.reply_text("Пожалуйста, введите корректное число.")
  136.         return
  137.    
  138.     chat_id = update.effective_chat.id
  139.     group_data = get_group_data(chat_id)
  140.    
  141.     if currency_name not in group_data.currencies:
  142.         update.message.reply_text("Валюта с таким названием не найдена.")
  143.         return
  144.    
  145.     group_data.currencies[currency_name].daily_reward = amount if amount > 0 else None
  146.    
  147.     if amount > 0:
  148.         update.message.reply_text(
  149.             f"Ежедневная награда для валюты {currency_name} установлена: {amount} {group_data.currencies[currency_name].emoji}"
  150.         )
  151.     else:
  152.         update.message.reply_text(
  153.             f"Ежедневная награда для валюты {currency_name} отключена."
  154.         )
  155.  
  156. def set_chat_reward(update: Update, context: CallbackContext):
  157.     if not is_admin(update):
  158.         update.message.reply_text("Только администраторы могут настраивать награды за сообщения.")
  159.         return
  160.    
  161.     if len(context.args) != 2:
  162.         update.message.reply_text(
  163.             "Использование: /setchatreward [название валюты] [количество]\n"
  164.             "Используйте 0 чтобы отключить награды за сообщения."
  165.         )
  166.         return
  167.    
  168.     currency_name, amount_str = context.args
  169.     try:
  170.         amount = int(amount_str)
  171.     except ValueError:
  172.         update.message.reply_text("Пожалуйста, введите корректное число.")
  173.         return
  174.    
  175.     chat_id = update.effective_chat.id
  176.     group_data = get_group_data(chat_id)
  177.    
  178.     if currency_name not in group_data.currencies:
  179.         update.message.reply_text("Валюта с таким названием не найдена.")
  180.         return
  181.    
  182.     group_data.currencies[currency_name].chat_reward = amount if amount > 0 else None
  183.    
  184.     if amount > 0:
  185.         update.message.reply_text(
  186.             f"Награда за сообщения для валюты {currency_name} установлена: {amount} {group_data.currencies[currency_name].emoji}"
  187.         )
  188.     else:
  189.         update.message.reply_text(
  190.             f"Награда за сообщения для валюты {currency_name} отключена."
  191.         )
  192.  
  193. def generate_currency(update: Update, context: CallbackContext):
  194.     if not is_admin(update):
  195.         update.message.reply_text("Только администраторы могут создавать валюту.")
  196.         return
  197.    
  198.     if len(context.args) != 3:
  199.         update.message.reply_text(
  200.             "Использование: /generate [@username] [название валюты] [количество]\n"
  201.             "Пример: /generate @user1 coins 100"
  202.         )
  203.         return
  204.    
  205.     username, currency_name, amount_str = context.args
  206.     try:
  207.         amount = int(amount_str)
  208.         if amount <= 0:
  209.             raise ValueError
  210.     except ValueError:
  211.         update.message.reply_text("Пожалуйста, введите положительное целое число.")
  212.         return
  213.    
  214.     chat_id = update.effective_chat.id
  215.     group_data = get_group_data(chat_id)
  216.    
  217.     if currency_name not in group_data.currencies:
  218.         update.message.reply_text("Валюта с таким названием не найдена.")
  219.         return
  220.    
  221.     # Получаем ID пользователя
  222.     if username.startswith('@'):
  223.         username = username[1:]
  224.         try:
  225.             user = context.bot.get_chat_member(chat_id, username)
  226.             user_id = user.user.id
  227.         except Exception as e:
  228.             update.message.reply_text(f"Не удалось найти пользователя {username}.")
  229. logger.error(f"Error finding user: {e}")
  230.             return
  231.     else:
  232.         try:
  233.             user_id = int(username)
  234.         except ValueError:
  235.             update.message.reply_text("Пожалуйста, укажите @username или ID пользователя.")
  236.             return
  237.    
  238.     if user_id not in group_data.user_balances:
  239.         group_data.user_balances[user_id] = {}
  240.    
  241.     if currency_name not in group_data.user_balances[user_id]:
  242.         group_data.user_balances[user_id][currency_name] = 0
  243.    
  244.     group_data.user_balances[user_id][currency_name] += amount
  245.    
  246.     try:
  247.         user = context.bot.get_chat_member(chat_id, user_id).user
  248.         user_name = user.username or user.first_name
  249.     except:
  250.         user_name = str(user_id)
  251.    
  252.     update.message.reply_text(
  253.         f"Пользователю {user_name} выдано {amount} {group_data.currencies[currency_name].emoji}!"
  254.     )
  255.  
  256. # ====================
  257. # Команды пользователей
  258. # ====================
  259.  
  260. def give_currency(update: Update, context: CallbackContext):
  261.     if update.effective_chat.type == 'private':
  262.         update.message.reply_text("Эта команда работает только в группах!")
  263.         return
  264.    
  265.     if len(context.args) != 3:
  266.         update.message.reply_text(
  267.             "Использование: /give [@username] [название валюты] [количество]\n"
  268.             "Пример: /give @user1 coins 50"
  269.         )
  270.         return
  271.    
  272.     username, currency_name, amount_str = context.args
  273.     try:
  274.         amount = int(amount_str)
  275.         if amount <= 0:
  276.             raise ValueError
  277.     except ValueError:
  278.         update.message.reply_text("Пожалуйста, введите положительное целое число.")
  279.         return
  280.    
  281.     chat_id = update.effective_chat.id
  282.     group_data = get_group_data(chat_id)
  283.    
  284.     if currency_name not in group_data.currencies:
  285.         update.message.reply_text("Валюта с таким названием не найдена.")
  286.         return
  287.    
  288.     sender_id = update.effective_user.id
  289.    
  290.     # Проверка баланса отправителя
  291.     if sender_id not in group_data.user_balances or currency_name not in group_data.user_balances[sender_id]:
  292.         update.message.reply_text(f"У вас нет валюты {currency_name}!")
  293.         return
  294.    
  295.     if group_data.user_balances[sender_id][currency_name] < amount:
  296.         update.message.reply_text("У вас недостаточно средств для перевода!")
  297.         return
  298.    
  299.     # Получаем получателя
  300.     if username.startswith('@'):
  301.         username = username[1:]
  302.         try:
  303.             receiver = context.bot.get_chat_member(chat_id, username)
  304.             receiver_id = receiver.user.id
  305.         except Exception as e:
  306.             update.message.reply_text(f"Не удалось найти пользователя {username}.")
  307.             logger.error(f"Error finding user: {e}")
  308.             return
  309.     else:
  310.         try:
  311.             receiver_id = int(username)
  312.         except ValueError:
  313.             update.message.reply_text("Пожалуйста, укажите @username или ID пользователя.")
  314.             return
  315.    
  316.     # Проверяем что пользователь не отправляет себе
  317.     if sender_id == receiver_id:
  318.         update.message.reply_text("Вы не можете отправить валюту самому себе!")
  319.         return
  320.    
  321.     # Снимаем валюту у отправителя
  322.     group_data.user_balances[sender_id][currency_name] -= amount
  323.    
  324.     # Добавляем получателю
  325.     if receiver_id not in group_data.user_balances:
  326.         group_data.user_balances[receiver_id] = {}
  327.    
  328.     if currency_name not in group_data.user_balances[receiver_id]:
  329.         group_data.user_balances[receiver_id][currency_name] = 0
  330.    
  331.     group_data.user_balances[receiver_id][currency_name] += amount
  332.    
  333.     # Получаем имена для сообщения
  334.     try:
  335.         sender_name = update.effective_user.username or update.effective_user.first_name
  336.         receiver_user = context.bot.get_chat_member(chat_id, receiver_id).user
  337.         receiver_name = receiver_user.username or receiver_user.first_name
  338. except Exception as e:
  339.         logger.error(f"Error getting user names: {e}")
  340.         sender_name = "Отправитель"
  341.         receiver_name = username
  342.    
  343.     currency = group_data.currencies[currency_name]
  344.     update.message.reply_text(
  345.         f"✅ {sender_name} передал {receiver_name} {amount} {currency.emoji}!"
  346.     )
  347.  
  348. def show_balance(update: Update, context: CallbackContext):
  349.     if update.effective_chat.type == 'private':
  350.         update.message.reply_text("Эта команда работает только в группах!")
  351.         return
  352.    
  353.     chat_id = update.effective_chat.id
  354.     user_id = update.effective_user.id
  355.     group_data = get_group_data(chat_id)
  356.    
  357.     if not group_data.currencies:
  358.         update.message.reply_text("В этой группе пока нет созданных валют.")
  359.         return
  360.    
  361.     if user_id not in group_data.user_balances or not group_data.user_balances[user_id]:
  362.         update.message.reply_text("У вас пока нет валюты.")
  363.         return
  364.    
  365.     balance_text = "💰 Ваш баланс:\n\n"
  366.     for currency_name, amount in group_data.user_balances[user_id].items():
  367.         currency = group_data.currencies.get(currency_name)
  368.         if currency:
  369.             balance_text += f"{currency.emoji} {currency.name}: {amount}\n"
  370.    
  371.     update.message.reply_text(balance_text)
  372.  
  373. def list_currencies(update: Update, context: CallbackContext):
  374.     """Показывает список всех валют в чате"""
  375.     if update.effective_chat.type == 'private':
  376.         update.message.reply_text("Эта команда работает только в группах!")
  377.         return
  378.    
  379.     chat_id = update.effective_chat.id
  380.     group_data = get_group_data(chat_id)
  381.    
  382.     if not group_data.currencies:
  383.         update.message.reply_text("В этой группе пока нет созданных валют.")
  384.         return
  385.    
  386.     message = "📊 Доступные валюты:\n\n"
  387.     for currency in group_data.currencies.values():
  388.         message += f"{currency.emoji} <b>{currency.name}</b>"
  389.         if currency.daily_reward:
  390.             message += f" | Ежедневно: +{currency.daily_reward}"
  391.         if currency.chat_reward:
  392.             message += f" | За сообщения: +{currency.chat_reward}"
  393.         message += "\n"
  394.    
  395.     update.message.reply_text(message, parse_mode='HTML')
  396.  
  397. def top_users(update: Update, context: CallbackContext):
  398.     """Показывает топ пользователей по валюте"""
  399.     if update.effective_chat.type == 'private':
  400.         update.message.reply_text("Эта команда работает только в группах!")
  401.         return
  402.    
  403.     if len(context.args) == 0:
  404.         update.message.reply_text("Использование: /top [название валюты]")
  405.         return
  406.    
  407.     currency_name = context.args[0]
  408.     chat_id = update.effective_chat.id
  409.     group_data = get_group_data(chat_id)
  410.    
  411.     if currency_name not in group_data.currencies:
  412.         update.message.reply_text("Валюта с таким названием не найдена.")
  413.         return
  414.    
  415.     # Собираем данные о пользователях
  416.     user_balances = []
  417.     for user_id, currencies in group_data.user_balances.items():
  418.         if currency_name in currencies:
  419.             user_balances.append((user_id, currencies[currency_name]))
  420.    
  421.     if not user_balances:
  422.         update.message.reply_text("Никто еще не получил эту валюту.")
  423.         return
  424.    
  425.     # Сортируем по убыванию баланса
  426.     user_balances.sort(key=lambda x: x[1], reverse=True)
  427.    
  428.     # Формируем сообщение (первые 10)
  429.     currency = group_data.currencies[currency_name]
  430.     message = f"🏆 Топ пользователей по валюте {currency.emoji} <b>{currency.name}</b>:\n\n"
  431.    
  432.     for i, (user_id, balance) in enumerate(user_balances[:10], 1):
  433.         try:
  434.             user = context.bot.get_chat_member(chat_id, user_id).user
  435.             username = f"@{user.username}" if user.username else user.first_name
  436.         except:
  437.             username = f"ID:{user_id}"
  438.        
  439.         message += f"{i}. {username}: {balance} {currency.emoji}\n"
  440.    
  441.     update.message.reply_text(message, parse_mode='HTML')
  442.  
  443. # ====================
  444. # Система автоматических наград
  445. # ====================
  446. def schedule_daily_tasks(updater: Updater):
  447.     """Запускает задачу для ежедневной выдачи наград"""
  448.     now = datetime.now(pytz.utc)
  449.    
  450.     # Вычисляем время до следующего дня (00:00 UTC)
  451.     next_day = now.replace(hour=0, minute=0, second=0, microsecond=0) + timedelta(days=1)
  452.     delay = (next_day - now).total_seconds()
  453.    
  454.     # Запускаем таймер
  455.     t = Timer(delay, daily_rewards_task, args=[updater])
  456.     t.start()
  457.  
  458. def daily_rewards_task(updater: Updater):
  459.     """Выдача ежедневных наград всем участникам чатов"""
  460.     try:
  461.         for chat_id, group_data in groups.items():
  462.             # Проверяем, есть ли валюты с ежедневными наградами
  463.             currencies_with_rewards = [
  464.                 currency for currency in group_data.currencies.values()
  465.                 if currency.daily_reward is not None and currency.daily_reward > 0
  466.             ]
  467.            
  468.             if not currencies_with_rewards:
  469.                 continue
  470.            
  471.             # Получаем всех участников чата
  472.             try:
  473.                 chat_members = updater.bot.get_chat_members(chat_id)
  474.                 member_ids = [member.user.id for member in chat_members]
  475.             except Exception as e:
  476.                 logger.error(f"Error getting chat members for chat {chat_id}: {e}")
  477.                 continue
  478.            
  479.             for user_id in member_ids:
  480.                 for currency in currencies_with_rewards:
  481.                     if user_id not in group_data.user_balances:
  482.                         group_data.user_balances[user_id] = {}
  483.                    
  484.                     if currency.name not in group_data.user_balances[user_id]:
  485.                         group_data.user_balances[user_id][currency.name] = 0
  486.                    
  487.                     group_data.user_balances[user_id][currency.name] += currency.daily_reward
  488.            
  489.             # Отправляем уведомление в чат
  490.             message = "🎉 Ежедневные награды выданы!\n\n"
  491.             for currency in currencies_with_rewards:
  492.                 message += f"{currency.emoji} {currency.name}: +{currency.daily_reward}\n"
  493.            
  494.             try:
  495.                 updater.bot.send_message(chat_id=chat_id, text=message)
  496.             except Exception as e:
  497.                 logger.error(f"Error sending daily reward message to chat {chat_id}: {e}")
  498.        
  499.         # Планируем следующую задачу
  500.         schedule_daily_tasks(updater)
  501.     except Exception as e:
  502.         logger.error(f"Error in daily rewards task: {e}")
  503.  
  504. def handle_message(update: Update, context: CallbackContext):
  505.     """Обработчик сообщений для выдачи наград за активность"""
  506.     if not update.message or not update.effective_chat or update.effective_chat.type == 'private':
  507.         return
  508.    
  509.     chat_id = update.effective_chat.id
  510.     user_id = update.effective_user.id
  511.    
  512.     # Игнорируем служебные сообщения
  513.     if update.message.left_chat_member or update.message.new_chat_members:
  514.         return
  515.    
  516.     # Инициализация структур данных если нужно
  517.     if chat_id not in user_last_message:
  518.         user_last_message[chat_id] = {}
  519.    
  520.     # Проверяем время последнего сообщения пользователя
  521.     last_message_time = user_last_message[chat_id].get(user_id)
  522.     now = datetime.now(pytz.utc)
  523.    
  524.     # Если сообщение отправлено слишком рано после предыдущего - игнорируем
  525.     if last_message_time and (now - last_message_time).total_seconds() < 60:
  526.         return
  527.    
  528.     user_last_message[chat_id][user_id] = now
  529.    
  530.     group_data = get_group_data(chat_id)
  531.    
  532.     # Выдаем награды за сообщения если есть
  533.     rewards_given = False
  534.     reward_message = ""
  535.    
  536.     for currency in group_data.currencies.values():
  537.         if currency.chat_reward and currency.chat_reward > 0:
  538.             if user_id not in group_data.user_balances:
  539.                 group_data.user_balances[user_id] = {}
  540. if currency.name not in group_data.user_balances[user_id]:
  541.                 group_data.user_balances[user_id][currency.name] = 0
  542.            
  543.             # Добавляем случайность
  544.             base_reward = currency.chat_reward
  545.             reward = base_reward
  546.            
  547.             # 30% шанс получить бонус
  548.             if random.random() < 0.3:
  549.                 reward = base_reward + random.randint(1, base_reward // 2)
  550.                 bonus = reward - base_reward
  551.                 reward_message = f" (+{bonus} бонус!)"
  552.            
  553.             group_data.user_balances[user_id][currency.name] += reward
  554.             rewards_given = True
  555. if rewards_given and random.random() < 0.2:  # 20% шанс уведомить о награде
  556.         try:
  557.             update.message.reply_text(
  558.                 f"💎 Вы получили награду за активность!{reward_message}",
  559.                 reply_to_message_id=update.message.message_id
  560.             )
  561.         except Exception as e:
  562.             logger.error(f"Error sending reward notification: {e}")
  563.  
  564. # ====================
  565. # Основная функция
  566. # ====================
  567.  
  568. def main() -> None:
  569.     # MyToken - токен моего бота (полученный от @BotFather)
  570.     updater = Updater("MyToken", use_context=True)
  571.     dispatcher = updater.dispatcher
  572.  
  573.     # ConversationHandler для создания валюты
  574.     conv_handler = ConversationHandler(
  575.         entry_points=[CommandHandler('createcurrency', start_currency_creation)],
  576.         states={
  577.             CURRENCY_NAME: [MessageHandler(Filters.text & ~Filters.command, process_currency_name)],
  578.             CURRENCY_EMOJI: [MessageHandler(Filters.text & ~Filters.command, process_currency_emoji)],
  579.         },
  580.         fallbacks=[CommandHandler('cancel', cancel_creation)],
  581.     )
  582.  
  583.     # Обработчики команд администраторов
  584.     dispatcher.add_handler(conv_handler)
  585.     dispatcher.add_handler(CommandHandler("setdaily", set_daily_reward))
  586.     dispatcher.add_handler(CommandHandler("setchatreward", set_chat_reward))
  587.     dispatcher.add_handler(CommandHandler("generate", generate_currency))
  588.    
  589.     # Обработчики команд пользователей
  590.     dispatcher.add_handler(CommandHandler("give", give_currency))
  591.     dispatcher.add_handler(CommandHandler("balance", show_balance))
  592.     dispatcher.add_handler(CommandHandler("currencies", list_currencies))
  593.     dispatcher.add_handler(CommandHandler("top", top_users))
  594.    
  595.     # Обработчик сообщений для наград за активность
  596.     dispatcher.add_handler(MessageHandler(Filters.text & ~Filters.command, handle_message))
  597.    
  598.     # Запускаем задачу для ежедневных наград
  599.     schedule_daily_tasks(updater)
  600.  
  601.     # Запуск бота
  602.     updater.start_polling()
  603.     logger.info("Бот запущен и работает...")
  604.     updater.idle()
  605.  
  606. if name == 'main':
  607.     main()
Advertisement
Add Comment
Please, Sign In to add comment