Современный бот-помощник для FunPay 🤖🟦
- 🎪 Удобное и понятное меню
- 💬 Отправка сообщений в чаты
- 🖼️ Отправка изображений в чаты
- 🛠️ Настройка конфигов
- 📊 Просмотр статистики (за 24 часа, неделю, месяц и всё время)
- 👤 Просмотр профиля (вся информация)
- 🗒️ Просмотр логов из консоли
- 🔔 Уведомления о событиях (новые сообщения, продажи...)
- ⚡ Быстрые ответы (сообщения по нажатию одной кнопки)
- 👤 Просмотр профиля
- и многое другое...
- 🧩 Система модулей (плагины, подключаемые к боту)
- 🟢 Вечный онлайн на сайте
- 🎈 Сообщения на события (приветственное, новая продажа...)
- ❗ Собственные команды
- 🚀 Авто-выдача товаров (поштучная и сообщением)
- ⬆️ Авто-поднятие лотов
- 📞 Авто-создание тикетов на закрытие заказов
- 🌐 Подключение прокси
- и многое другое...
- Установите Python версии 3.12.x (на других версиях работа бота не гарантируется), перейдя по ссылке https://www.python.org/downloads/release/python-31210/ (при установке нажмите на пункт
Add to PATH). - Скачайте последнюю Release версию и распакуйте в любое удобное для вас место.
- Откройте
install.batи дождитесь установки всех необходимых зависимостей, а после закройте окно. - Чтобы запустить бота, откройте запускатор
start.bat. - После первого запуска следуйте действиям в консоли.
Возникли проблемы с установкой? Нажми на меня
- Установите Python версии 3.12.x с официального сайта или через Homebrew:
brew install python@3.12
- Скачайте последнюю Release версию и распакуйте в любое удобное место.
- Дважды кликните
install_mac.command— откроется Terminal, дождитесь установки зависимостей. - Запустите бота двойным кликом по
start_mac.command. - Следуйте инструкциям в консоли.
- Выполните команду
bash <(curl -s https://raw.githubusercontent.com/alleexxeeyy/funpay-universal/main/install.sh) - Следуйте инструкциям установщика. Он автоматически установит все необходимые для работы компоненты.
🕹️ Команды для управления
| Команда | Что делает |
|---|---|
fpuniversal |
🕹️ Меню с командами |
fpuniversal setup |
⚙️ Первичная настройка |
fpuniversal start |
🟢 Запуск бота |
fpuniversal stop |
⛔ Остановка бота |
fpuniversal restart |
🔄️ Перезапуск бота |
fpuniversal status |
📈 Статус бота |
fpuniversal log |
🗒️ Логи бота |
fpuniversal log100 |
📃 Последние 100 логов |
fpuniversal update |
🔵 Обновление бота |
fpuniversal enable |
☑️ Включить авто-запуск бота |
fpuniversal disable |
❌ Выключить авто-запуск бота |
Модульная система помогает внедрять в бота дополнительный функционал, сделанный энтузиастами. По сути, это же, что и плагины, но в более удобном формате. Вы можете создавать свой модуль, опираясь на шаблонный.
📌 Основные ивенты
Ивенты, которые выполняются при определённом действии бота.
| Ивент | Когда вызывается | Передающиеся аргументы |
|---|---|---|
ON_MODULE_ENABLED |
При включении модуля (включая первое подключение и перезагрузку) | Module |
ON_MODULE_DISABLED |
При выключении модуля (включая перезагрузку) | Module |
ON_INIT |
При инициализации бота | - |
ON_FUNPAY_BOT_INIT |
При инициализации (запуске) FunPay бота | FunPayBot |
ON_TELEGRAM_BOT_INIT |
При инициализации (запуске) Telegram бота | TelegramBot |
Ивенты, получаемые в слушателе событий в FunPay боте.
| Ивент | Когда вызывается | Передающиеся аргументы |
|---|---|---|
EventTypes.CHAT_INITIALIZED |
Чат инициализирован | FunPayBot, ChatInitializedEvent |
EventTypes.NEW_MESSAGE |
Новое сообщение в чате | FunPayBot, NewMessageEvent |
EventTypes.NEW_DEAL |
Создана новая сделка (когда покупатель оплатил товар) | FunPayBot, NewDealEvent |
EventTypes.NEW_REVIEW |
Новый отзыв по сделке | FunPayBot, NewReviewEvent |
EventTypes.DEAL_CONFIRMED |
Сделка подтверждена | FunPayBot, DealConfirmedEvent |
EventTypes.DEAL_ROLLED_BACK |
Продавец оформил возврат сделки | FunPayBot, DealRolledBackEvent |
EventTypes.DEAL_HAS_PROBLEM |
Пользователь сообщил о проблеме в сделке | FunPayBot, DealHasProblemEvent |
EventTypes.DEAL_PROBLEM_RESOLVED |
Проблема в сделке решена | FunPayBot, DealProblemResolvedEvent |
EventTypes.DEAL_STATUS_CHANGED |
Статус сделки изменён | FunPayBot, DealStatusChangedEvent |
EventTypes.ITEM_PAID |
Пользователь оплатил предмет | FunPayBot, ItemPaidEvent |
EventTypes.ITEM_SENT |
Предмет отправлен (продавец подтвердил выполнение сделки) | FunPayBot, ItemSentEvent |
📁 Строение модуля
Модуль - это папка, внутри которой находятся важные компоненты. Вы можете изучить строение модуля, опираясь на шаблонный модуль, но стоит понимать, что это лишь пример, сделанный нами.
Обязательные константы хендлеров:
| Константа | Тип | Описание |
|---|---|---|
BOT_EVENT_HANDLERS |
dict[str, list[Any]] |
В этом словаре задаются хендлеры ивентов бота |
FUNPAY_EVENT_HANDLERS |
dict[EventTypes, list[Any] |
В этом словаре задаются хендлеры ивентов FunPay |
TELEGRAM_BOT_ROUTERS |
list[Router] |
В этом массиве задаются роутеры модульного Telegram бота |
Обязательные константы метаданных:
| Константа | Тип | Описание |
|---|---|---|
PREFIX |
str |
Префикс |
VERSION |
str |
Версия |
NAME |
str |
Название |
DESCRIPTION |
str |
Описание |
AUTHORS |
str |
Авторы |
LINKS |
str |
Ссылки на авторов |
Также, если модуль требует дополнительных зависимостей, в нём должен быть файл зависимостей requirements.txt, которые будут сами скачиваться при загрузке всех модулей бота.
Обратите внимание, что метаданные были вынесены в отдельный файл meta.py, но импортируются в __init__.py.
Это сделано для избежания конфликтов импорта в дальнейшей части кода модуля.
meta.py:
from colorama import Fore, Style
PREFIX = f"{Fore.LIGHTCYAN_EX}[test module]{Fore.WHITE}"
VERSION = "0.1"
NAME = "test_module"
DESCRIPTION = "Тестовый модуль. /test_module в Telegram боте для управления"
AUTHORS = "@alleexxeeyy"
LINKS = "https://t.me/alleexxeeyy, https://t.me/alexeyproduction"__init__.py:
from FunPayApi.common.enums import EventTypes
from core.modules_manager import Module, disable_module
from .plbot.handlers import on_funpay_bot_init, on_new_message, on_new_deal
from .tgbot import router
from .tgbot._handlers import on_telegram_bot_init
from .meta import *
_module: Module = None
def set_module(module: Module):
global _module
_module = module
def get_module():
return _module
async def on_module_enabled(module: Module):
try:
set_module(module)
print(f"{PREFIX} Модуль подключен и активен")
except:
await disable_module(_module.uuid)
BOT_EVENT_HANDLERS = {
"ON_MODULE_ENABLED": [on_module_enabled],
"ON_FUNPAY_BOT_INIT": [on_funpay_bot_init],
"ON_TELEGRAM_BOT_INIT": [on_telegram_bot_init]
}
FUNPAY_EVENT_HANDLERS = {
EventTypes.NEW_MESSAGE: [on_new_message],
EventTypes.NEW_DEAL: [on_new_deal],
# ...
}
TELEGRAM_BOT_ROUTERS = [router]🛠️ Полезные инструменты
Вместо того, чтобы лишний раз мучаться с файлами конфигурациями, написанием кода для управлениями ими, мы подготовили для вас готовое решение.
У бота есть уже настроенные классы в файлах settings.py и data.py
Допустим, вы хотите создать файл конфигурации в своём модуле, для этого вам нужно будет создать файл settings.py в корне папки модуля.
Содержимое settings.py должно быть примерно следующим:
import os
from settings import (
Settings as sett,
SettingsFile
)
CONFIG = SettingsFile(
name="config", # название файла конфигурации
path=os.path.join(os.path.dirname(__file__), "module_settings", "config.json"), # путь к файлу конфигурации (в данном случае относительно папки модуля)
need_restore=True, # нужно ли восстанавливать конфиг
default={
"bool_param": True,
"str_param": "qwerty",
"int_param": 123
} # стандартное содержимое файла
)
DATA = [CONFIG]
class Settings:
@staticmethod
def get(name: str) -> dict:
return sett.get(name, DATA)
@staticmethod
def set(name: str, new: list | dict) -> dict:
return sett.set(name, new, DATA)Файл конфигурации задаётся с помощью датакласса SettingsFile, который в свою очередь, передаётся в массив DATA.
Далее, получить данные из конфига или сохранить данные в конфиг можно вот так:
from . import settings as sett
config = sett.get("config") # получаем конфиг
print(config["bool_param"]) # -> True
print(config["str_param"]) # -> qwerty
print(config["int_param"]) # -> 123
config["bool_param"] = False
config["str_param"] = "uiop"
config["int_param"] = 456
sett.set("config", config) # задаём конфигу новое значениеЗадавая конфигу новое значение, оно сразу записывается в его файл. Также и при получении, берутся актуальные данные из файла.
Описание аргументов датакласса SettingsFile:
| Аргумент | Описание |
|---|---|
name |
Название файла конфигурации, которое будем использовать при получении и записи |
path |
Путь к файлу конфигурации |
need_restore |
Нужно ли восстанавливать конфиг? Допустим, в стандартное значение конфига у вас добавились новые данные, а в уже созданном ранее файле конфигурации они отсутствуют. Если параметр включен, скрипт будет сверять текущие данные конфига со стандартными указанными, и если в текущих данных не будет того или иного ключа, который есть в стандартном значении, он автоматически добавится в конфиг. Так же, если тип значения ключа стандартного конфига не соответствует существующему (например, в файле строковый тип, а в стандартном значении числовой), также этот ключ в текущем конфиге будет заменён на стандартное значение |
default |
Стандартное значение файла конфигурации |
Точно также устроен и файл данных, но он нужен для хранения информации, собранной самим скриптом, а не указанной пользователей.
Например, вы хотите создать файл данных в своём модуле, для этого вам нужно будет создать файл data.py в корне папки модуля.
Содержимое data.py должно быть примерно следующим:
import os
from data import (
Data as data,
DataFile
)
LATEST_EVENTS_TIMES = DataFile(
name="new_forms", # название файла данных
path=os.path.join(os.path.dirname(__file__), "module_data", "new_forms.json"), # путь к файлу данных (в данном случае относительно папки модуля)
default={} # стандартное содержимое файла
)
DATA = [LATEST_EVENTS_TIMES]
class Data:
@staticmethod
def get(name: str) -> dict:
return data.get(name, DATA)
@staticmethod
def set(name: str, new: list | dict) -> dict:
return data.set(name, new, DATA)Здесь всё аналогично файлу конфигурации, только служит для другой задачи.
Используя методы из core/modules.py, можно удобно включать/выключать/перезагружать текущий модуль.
Для того, чтобы это сделать, нужно прежде всего получить UUID текущего запущенного модуля, который генерируется при его инициализации.
Например, в файле __init__.py можно делать так:
# import ...
_module: Module = None
async def set_module(module: Module):
global _module
_module = module
def get_module():
return _module
BOT_EVENT_HANDLERS = {
"ON_MODULE_ENABLED": [set_module],
# ...
}
# ...А потом в любом удобном месте управлять модулем:
from core.modules import enable_module, disable_module, reload_module
from . import get_module
await disable_module(get_module().uuid) # выключает модуль
await enable_module(get_module().uuid) # включает модуль
await reload_module(get_module().uuid) # перезагружает модуль❗ Примечания
Функционал Telegram бота написан на библиотеке aiogram 3, система внедрения пользовательского функционала Telegram бота работает на основе роутеров, которые сливаются с основным, главным роутером бота.
И так, как они сливаются воедино, могут возникнуть осложнения, если, например Callback данные имеют идентичное название. Поэтому, после написания функционала Telegram бота для модуля, лучше переименуйте
эти данные уникальным образом, чтобы они не совпадали с названиями основного бота или дополнительных подключаемых модулей.
- Разработчик: @alleexxeeyy
- Новости: @alexeyproduction
- Плагины: @alexey_production_bot