import json
import logging
import os
import re
import threading
from datetime import datetime
from typing import TYPE_CHECKING, Optional, List, Dict
import requests
import telebot
from telebot import types
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
from cardinal import Cardinal
if TYPE_CHECKING:
from cardinal import Cardinal
from FunPayAPI.updater.events import *
from FunPayAPI.types import MessageTypes
from locales.localizer import Localizer
from tg_bot.utils import load_authorized_users
pending_confirmations = {}
logger = logging.getLogger("FPC.AutoSmm")
localizer = Localizer()
_ = localizer.translate
LOGGER_PREFIX = "AutoSmm Plugin"
NAME = "AUTOSMM"
VERSION = "0.0.13"
CREDITS = "@klaymov"
UUID = "7aa412ab-0840-455d-9513-6f51bf83d43b"
SETTINGS_PAGE = False
ORDERS_FILE = f"storage/plugins/{UUID}/orders.json"
PAYORDERS_FILE = f"storage/plugins/{UUID}/payorders.json"
SETTINGS_FILE = f"storage/plugins/{UUID}/settings.json"
CASHLIST_FILE = f"storage/plugins/{UUID}/cashlist.json"
REFILL_FILE = f"storage/plugins/{UUID}/refill.json"
DEFAULT_SETTINGS = {
"api_url": "",
"api_key": "",
"set_alert_neworder": True,
"set_alert_errororder": True,
"set_alert_smmbalance_new": False,
"set_alert_smmbalance": True,
"set_refund_smm": True,
"set_start_mess": True,
"set_auto_refill": False,
"set_tg_private": False
}
# список для чекера заказов
def load_orders() -> dict:
if os.path.exists(ORDERS_FILE):
with open(ORDERS_FILE, "r") as file:
return json.load(file)
return {}
def save_orders(orders: dict) -> None:
os.makedirs(f"storage/plugins/{UUID}", exist_ok=True)
with open(ORDERS_FILE, "w") as file:
json.dump(orders, file, indent=4)
# список для новых оплаченных заказов
def load_payorders() -> List[Dict]:
if os.path.exists(PAYORDERS_FILE):
with open(PAYORDERS_FILE, "r") as file:
return json.load(file)
return []
def save_payorders(orders: List[Dict]) -> None:
os.makedirs(f"storage/plugins/{UUID}", exist_ok=True)
with open(PAYORDERS_FILE, "w") as file:
json.dump(orders, file, indent=4)
# временный список для пересозданных заказов
def load_cashlist() -> dict:
if os.path.exists(CASHLIST_FILE):
with open(CASHLIST_FILE, "r") as file:
return json.load(file)
return {}
def save_cashlist(orders: dict) -> None:
os.makedirs(f"storage/plugins/{UUID}", exist_ok=True)
with open(CASHLIST_FILE, "w") as file:
json.dump(orders, file, indent=4)
# список для рефилла
def load_refill() -> dict:
if os.path.exists(REFILL_FILE):
with open(REFILL_FILE, "r") as file:
return json.load(file)
return {}
def save_refill(orders: dict) -> None:
os.makedirs(f"storage/plugins/{UUID}", exist_ok=True)
with open(REFILL_FILE, "w") as file:
json.dump(orders, file, indent=4)
# Загружает настройки из файла или создает новые, если файла нет.
def load_settings():
if not os.path.exists(SETTINGS_FILE):
# Файла не существует, создаем новый
settings = DEFAULT_SETTINGS.copy()
save_settings(settings)
with open(SETTINGS_FILE, 'r') as file:
return json.load(file)
def save_settings(settings):
os.makedirs(f"storage/plugins/{UUID}", exist_ok=True)
with open(SETTINGS_FILE, 'w') as file:
json.dump(settings, file, indent=4)
def get_api_url(type=None):
"""Возвращает URL API из настроек."""
settings = load_settings()
if type:
return settings.get("api_url_2", "")
return settings.get("api_url", "")
def get_api_key(type=None):
"""Возвращает ключ API из настроек."""
settings = load_settings()
if type:
return settings.get("api_key_2", "")
return settings.get("api_key", "")
def extract_links(text: str) -> List[str]:
"""
Парсит ссылку из сообщения
"""
link_pattern = r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
return re.findall(link_pattern, text)
def find_order_by_buyer(orders: List[Dict], buyer: str) -> Optional[Dict]:
"""
Ищем ордер по имени покупателя
"""
for order in orders:
if order['buyer'] == buyer:
return order
return None
def bind_to_new_order(c: Cardinal, e: NewOrderEvent) -> None:
try:
_element_data = e.order
_order_id = _element_data.id
_element_full_data = c.account.get_order(_order_id)
_full_disc = _element_full_data.full_description
_buyer_uz = _element_full_data.buyer_username
settings = load_settings()
if settings.get("set_alert_smmbalance_new", False):
send_smm_balance_info(c)
match_id = re.search(r'ID:\s*(\d+)', _full_disc)
match_oid = re.search(r'ID2:\s*(\d+)', _full_disc)
match_quan = re.search(r'#Quan:\s*(\d+)', _full_disc)
if match_id:
id_value = match_id.group(1)
if match_quan:
quan_value = int(match_quan.group(1))
else:
quan_value = 1
order_handler(c, e, id_value, quan_value, _buyer_uz)
elif match_oid:
id_value = match_oid.group(1)
if match_quan:
quan_value = int(match_quan.group(1))
else:
quan_value = 1
order_handler(c, e, id_value, quan_value, _buyer_uz, 'API_2')
else:
logger.info("Заказ не найден для автонакрутки")
except Exception as ex:
logger.error(ex)
def order_handler(c: Cardinal, e: NewOrderEvent, id_value, quan_value, buyer_uz, type_api='API_1') -> None:
try:
orders_data = load_payorders()
order_ = e.order
orderID = order_.id
orderAmount = order_.amount * quan_value # умножаем количество на значение из #Quan:
orderPrice = order_.price
orderCurrency = order_.currency
url = ""
current_datetime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") #час бачив? пісяти і спати
current_order_data = {
'OrderID': str(orderID),
'Amount': int(orderAmount),
'OrderPrice': orderPrice,
'OrderCurrency': f"{orderCurrency}",
'Order': f"{str(order_)}",
'service_id': int(id_value),
'buyer': str(buyer_uz),
'url': str(url),
'NewUser': True,
'chat_id': "",
'OrderDateTime': current_datetime,
'api_type': type_api # Тип API, default api 1
}
orders_data.append(current_order_data)
save_payorders(orders_data)
handle_order(c, current_order_data, [])
except Exception as ex:
logger.error(f"Ошибка при обработке нового заказа: {ex}")
logger.info(f"$MAGENTA{LOGGER_PREFIX} успешно запущен.$RESET")
DESCRIPTION = "Плагин добавляет возможность автонакрутки с api-V2!"
def msg_hook(c: Cardinal, e: NewMessageEvent) -> None:
"""
Обрабатывает новое сообщение
"""
orders_data = load_payorders()
msg = e.message
msgname = msg.chat_name
message_text = msg.text.strip()
order = find_order_by_buyer(orders_data, msgname)
try:
api_key = get_api_key() if order.get('api_type') == 'API_1' else get_api_key(order.get('api_type'))
api_url = get_api_url() if order.get('api_type') == 'API_1' else get_api_url(order.get('api_type'))
except Exception as e:
api_key = get_api_key()
api_url = get_api_url()
# Удаление пользователя из списка при отмене заказа
if "вернул деньги покупателю" in message_text:
order = find_order_by_buyer(orders_data, msgname)
if order:
try:
orders_data.remove(order)
save_payorders(orders_data)
except Exception as e:
logger.error(f"Ошибка при возврате: {e}")
return
# Проверка на системные сообщения
if msg.type != MessageTypes.NON_SYSTEM:
logger.info("Ignoring system message.")
return
# Проверка на свои сообщения
if msg.author_id == c.account.id:
return
# Проверяем, есть ли ожидаемое подтверждение
if msg.chat_id in pending_confirmations:
if message_text in ["+", "-"]:
confirm_order(c, msg.chat_id, message_text, api_url, api_key)
elif "http" in message_text: # Проверяем, содержит ли сообщение ссылку
order = pending_confirmations.get(msg.chat_id)
if order:
order['chat_id'] = msg.chat_id
links = extract_links(message_text)
handle_order(c, order, links)
else:
c.send_message(msg.chat_id, "⚪️ Пожалуйста, отправьте +, если всё верно, или -, для возврата средств.")
return
# Ищем ордер по имени покупателя
order = find_order_by_buyer(orders_data, msgname)
if order:
logger.info(f"Пользователь {msgname} есть в списке заказов")
order['chat_id'] = msg.chat_id
links = extract_links(message_text)
handle_order(c, order, links)
else:
logger.info(f"Пользователя {msgname} нету в списке заказов автонакрутки")
command_parts = msg.text.split()
if len(command_parts) >= 2 and command_parts[0] == "#статус":
smm_order_id = command_parts[1]
status = SocTypeAPI.get_order_status(int(smm_order_id), api_url, api_key)
if status:
start_count = status['start_count']
if start_count == 0:
display_start_count = "*"
else:
display_start_count = str(start_count)
status_text = f"📈 Статус заказа: {smm_order_id}\n"
status_text += f"⠀∟📊 Статус: {status['status']}\n"
status_text += f"⠀∟🔢 Было: {display_start_count}\n"
status_text += f"⠀∟👀 Остаток выполнения: {status['remains']}"
c.send_message(msg.chat_id, status_text)
else:
c.send_message(msg.chat_id, "🔴 Не удалось получить статус заказа.")
if len(command_parts) >= 2 and command_parts[0] == "#инфо":
smm_order_id = command_parts[1]
status = SocTypeAPI.get_order_status(int(smm_order_id), get_api_url('API_2'), get_api_key('API_2'))
if status:
start_count = status['start_count']
if start_count == 0:
display_start_count = "*"
else:
display_start_count = str(start_count)
status_text = f"📈 Статус заказа: {smm_order_id}\n"
status_text += f"⠀∟📊 Статус: {status['status']}\n"
status_text += f"⠀∟🔢 Было: {display_start_count}\n"
status_text += f"⠀∟👀 Остаток выполнения: {status['remains']}"
c.send_message(msg.chat_id, status_text)
else:
c.send_message(msg.chat_id, "🔴 Не удалось получить статус заказа.")
elif len(command_parts) >= 2 and command_parts[0] == "#рефилл":
smm_order_id = command_parts[1]
refill_result = SocTypeAPI.refill_order(int(smm_order_id), api_url, api_key)
if refill_result is not None:
c.send_message(msg.chat_id, f"✅ Запрос на рефилл отправлен!")
else:
c.send_message(msg.chat_id, f"🔴 Ошибка при выполнении рефилла.\n⚠️ Возможно, рефилл еще недоступен!")
def handle_order(c: Cardinal, order: Dict, links: List[str]) -> None:
"""
Логика обработки сообщений от покупателя
"""
if links:
link = links[0]
orders_data = load_payorders()
settings = load_settings()
if not settings.get("set_tg_private", False):
if "t.me" in link and ("/c/" in link or "+" in link):
c.send_message(order['chat_id'], "❌ Данный тип ссылки не поддерживается. Канал/группа должны быть публичными!")
return
order['url'] = link
link = link.replace("https://", "")
confirmation_text = f"""📋 Пожалуйста, проверьте детали вашего заказа:
🛒 Лот: {order['Order']}
🔢 Количество: {order['Amount']} шт
🔗 Ссылка: {link}
✅ Если всё верно, отправьте: +
❌ Для возврата средств, отправьте: -
🔄 Или отправьте новую ссылку для обновления.
"""
c.send_message(order['chat_id'], confirmation_text)
pending_confirmations[order['chat_id']] = order
# сохранение в json (нужно!)
orders_data = load_payorders()
existing_order = next((o for o in orders_data if o['OrderID'] == order['OrderID']), None)
if existing_order:
existing_order.update(order)
else:
orders_data.append(order)
save_payorders(orders_data)
def confirm_order(c: Cardinal, chat_id: int, text: str, api_url, api_key) -> None:
"""
Подтверждает заказ, если пользователь отправил "+"
"""
orders_data = load_payorders()
settings = load_settings()
if chat_id in pending_confirmations:
order = pending_confirmations.pop(chat_id)
if text.strip() == "+":
try:
smm_order_id = SocTypeAPI.create_order(order['service_id'], order['url'], order['Amount'], api_url, api_key)
except Exception as e:
logger.error(f"{e}")
if isinstance(smm_order_id, (int, str)) and str(smm_order_id).isdigit():
try:
orders = load_orders()
orders[smm_order_id] = {
"service_id": order['service_id'],
"chat_id": order['chat_id'],
"order_id": order['OrderID'],
"order_url": order['url'],
"order_amount": order['Amount'],
"partial_amount": 0,
"orderdatetime": order['OrderDateTime'],
"status": "pending"
}
save_orders(orders)
# отправка сообщения в тг
if settings.get("set_alert_neworder", False):
send_order_info(c, order, int(smm_order_id), api_url, api_key)
except Exception as e:
logger.error(f"{e}")
status = 'статус' if order.get('api_type') == 'API_1' else 'инфо'
c.send_message(order['chat_id'],
f"""📊 Ваш заказ СОЗДАН и отправлен SMM сервису!
🆔 ID заказа: {smm_order_id}
📋 Доступные команды:
⠀∟📗 Узнать статус заказа: #{status} {smm_order_id}
⠀∟📙 Рефилл (если доступно): #рефилл {smm_order_id}
⌛ Время выполнения: от нескольких минут до 48 часов. В редких случаях возможны задержки.
""")
else:
c.send_message(order['chat_id'], f"❌ Ошибка при создании заказа: {smm_order_id}")
# отправка сообщения в тг
if settings.get("set_alert_errororder", False):
send_order_error_info(c, smm_order_id, order)
if settings.get("set_alert_smmbalance", False):
send_smm_balance_info(c)
if settings.get("set_refund_smm", False):
try:
c.account.refund(order['OrderID'])
except Exception as e:
logger.error(f"Ошибка при возврате средств: {e}")
else:
if text.strip() == "-":
c.send_message(chat_id, "❌ Заказ отменен.\n")
try:
c.account.refund(order['OrderID'])
except Exception as e:
pass
orders_data.remove(order)
save_payorders(orders_data)
# телеграм
def send_order_info(c: Cardinal, order: Dict, smm_order_id: int, api_url, api_key) -> None:
"""
Инфа в телеграм о новом заказе
"""
def getcoingaterate(fromcurrency='USD', tocurrency='RUB'):
try:
url = f'https://api.coingate.com/v2/rates/merchant/{fromcurrency}/{tocurrency}'
response = requests.get(url)
response.raise_for_status()
return float(response.text)
except Exception as e:
logger.error(f"Ошибка при получении курса: {e}")
return None
fp_balance = c.get_balance()
price_smm_order = SocTypeAPI.get_order_status(smm_order_id, api_url, api_key)['charge']
currency = SocTypeAPI.get_order_status(smm_order_id, api_url, api_key)['currency']
smm_balance_info = SocTypeAPI.get_balance(api_url, api_key)
balance, currency = smm_balance_info
fp_currency = order['OrderCurrency']
if fp_currency == '₽':
if currency == 'RUB':
pass
elif currency == 'USD':
price_smm_order = float(price_smm_order) * float(getcoingaterate('USD', 'RUB'))
elif fp_currency == '$':
if currency == 'RUB':
price_smm_order = float(price_smm_order) * float(getcoingaterate('RUB', 'USD'))
elif currency == 'USD':
pass
sum_order = float(order['OrderPrice']) - float(price_smm_order)
sum_order_6com = sum_order * 0.94 # 6% комиссию за вывод
sum_order_3com = sum_order * 0.97 # 3% комиссию за вывод
order_info = (
f"<b>✅ Создан заказ <code>{NAME}</code>:</b> <code>{order['Order']}</code>\n\n"
f"<b><i>🙍♂️ Покупатель:</i></b> <code>{order['buyer']}</code>\n\n"
f"<b><i>💵 Сумма заказа:</i></b> <code>{order['OrderPrice']} {fp_currency}</code>\n"
f"<b><i>💵 Потрачено:</i></b> <code>{price_smm_order} {currency}</code>\n"
f"<b><i>💵 Прибыль:</i></b> {order['OrderPrice']}-{price_smm_order} = <code>{sum_order:.2f}</code>\n"
f"<b><i>💵 Прибыль с комисией:</i></b> <code>{sum_order_6com:.2f} 6% {sum_order_3com:.2f} 3%</code>\n"
f"<b><i>💰 Остаток на балансе:</i></b> <code>{balance:.2f} {currency}</code>\n"
f"<b><i>💰 Баланс на FunPay:</i></b> <code>{fp_balance.total_rub}₽, {fp_balance.available_usd}$, {fp_balance.total_eur}€</code>\n\n"
f"<b><i>📇 ID заказа на FunPay:</i></b> <code>{order['OrderID']}</code>\n"
f"<b><i>🆔 ID заказа на сайте:</i></b> <code>{smm_order_id}</code>\n"
f"<b><i>🔍 Сервис ID:</i></b> <code>{order['service_id']}</code>\n"
f"<b><i>🔢 Кол-во:</i></b> <code>{order['Amount']}</code>\n"
f"<b><i>🔗 Ссылка:</i></b> {order['url'].replace('https://', '')}\n\n"
)
button = InlineKeyboardButton(text="🌐 Открыть страницу заказа", url=f"https://funpay.com/orders/{order['OrderID']}/")
keyboard = InlineKeyboardMarkup().add(button)
try:
users = load_authorized_users()
if not users:
return
for user_id in users:
c.telegram.bot.send_message(
user_id,
order_info,
parse_mode='HTML',
reply_markup=keyboard,
disable_web_page_preview=True
)
except Exception as e:
logging.error(e)
def send_order_error_info(c: Cardinal, text: Dict, order: Dict) -> None:
"""
Инфа в телеграм о ошибке при создании заказа
"""
text_error = (
f"<b>❌ Ошибка при создании заказа <code>{NAME}<code> #{order['OrderID']}:</b> <code>{text}</code>\n\n"
)
button = InlineKeyboardButton(text="🌐 Открыть страницу заказа", url=f"https://funpay.com/orders/{order['OrderID']}/")
keyboard = InlineKeyboardMarkup().add(button)
try:
users = load_authorized_users()
if not users:
return
for user_id in users:
c.telegram.bot.send_message(
user_id,
text_error,
parse_mode='HTML',
reply_markup=keyboard,
disable_web_page_preview=True
)
except Exception as e:
logging.error(e)
def send_smm_balance_info(c: Cardinal) -> None:
"""
Инфа в телеграм о балансе смм
"""
try:
fp_balance = c.get_balance()
api_url = get_api_url()
api_key = get_api_key()
smm_balance_info = SocTypeAPI.get_balance(api_url, api_key)
balance, currency = smm_balance_info
api_url_2 = get_api_url('2')
api_key_2 = get_api_key('2')
smm_balance_info_2 = SocTypeAPI.get_balance(api_url_2, api_key_2)
balance_2, currency_2 = smm_balance_info_2
text_balance = (
f"<b>💰 Баланс {api_url.replace('https://', '').replace('/api/v2/', '').replace('/api/v2', '')}:</b> <code>{balance:.2f} {currency}</code>\n"
f"<b>💰 Баланс {api_url_2.replace('https://', '').replace('/api/v2/', '').replace('/api/v2', '')}:</b> <code>{balance_2:.2f} {currency_2}</code>\n"
f"<b>💰 Баланс на FunPay:</b> <code>{fp_balance.total_rub}₽, {fp_balance.available_usd}$, {fp_balance.total_eur}€</code>"
)
except Exception as e:
api_url = get_api_url()
api_key = get_api_key()
smm_balance_info = SocTypeAPI.get_balance(api_url, api_key)
balance, currency = smm_balance_info
text_balance = (
f"<b>💰 Баланс сайта:</b> <code>{balance:.2f} {currency}</code>\n"
f"<b>💰 Балансе на FunPay:</b> <code>{fp_balance.total_rub}₽, {fp_balance.available_usd}$, {fp_balance.total_eur}€</code>"
)
try:
users = load_authorized_users()
if not users:
return
for user_id in users:
c.telegram.bot.send_message(
user_id,
text_balance,
parse_mode='HTML'
)
except Exception as e:
logging.error(e)
def send_smm_start_info(c: Cardinal) -> None:
"""
Инфа в телеграм при старте бота
"""
text_start = (
f"<b><u>✅ Авто-накрутка инициализирована!</u></b>\n\n"
f"<b><i>ℹ️ Версия:</i></b> <code>{VERSION}</code>\n"
f"<b><i>⚙️ Настройки /autosmm</i></b>\n\n"
f"<i>ℹ️ Авто-накрутка by @klaymov</i>"
)
try:
users = load_authorized_users()
if not users:
return
for user_id in users:
c.telegram.bot.send_message(
user_id,
text_start,
parse_mode='HTML'
)
except Exception as e:
logging.error(e)
###
class SocTypeAPI:
@staticmethod
def create_order(service_id: int, link: str, quantity: int, api_url: str, api_key: str) -> Optional[int]:
url = f"{api_url}?action=add&service={service_id}&link={link}&quantity={quantity}&key={api_key}"
try:
response = requests.get(url)
response.raise_for_status()
response_json = response.json()
if "order" in response_json:
return response_json["order"]
elif "error" in response_json:
return response_json["error"]
else:
logger.error(f"Ошибка при создании заказа: {response_json}")
return "Неизвестная ошибка при создании заказа."
except requests.exceptions.HTTPError as http_err:
try:
error_response = response.json()
if "error" in error_response:
return error_response["error"]
except ValueError:
logger.error(f"HTTP ошибка: {http_err} - Ответ от сервера: {response.text}")
return "Неизвестная ошибка при создании заказа."
@staticmethod
def get_order_status(order_id: int, api_url: str, api_key: str) -> Optional[dict]:
url = f"{api_url}?action=status&order={order_id}&key={api_key}"
try:
response = requests.get(url)
response.raise_for_status()
order_status = response.json()
return order_status
except requests.exceptions.RequestException as ex:
logger.error(f"Error getting SocType order status: {ex}")
return None
@staticmethod
def refill_order(order_id: int, api_url: str, api_key: str) -> Optional[str]:
url = f"{api_url}?action=refill&order={order_id}&key={api_key}"
try:
response = requests.get(url)
response.raise_for_status()
refill = response.json().get("refill")
return refill
except requests.exceptions.RequestException as ex:
logger.error(f"Error refilling SocType order: {ex}")
return None
@staticmethod
def get_balance(api_url: str, api_key: str):
url = f"{api_url}?action=balance&key={api_key}"
try:
response = requests.get(url)
response.raise_for_status()
balance_data: Dict[str, str] = response.json()
pattern = r'\d+\.\d+'
match = re.search(pattern, balance_data['balance'])
if match:
balance = float(match.group())
currency = balance_data['currency']
return balance, currency
else:
raise ValueError("Invalid balance format")
except Exception as e:
logger.error(f"Ошибка при получения баланса сайта, возможно неверный API: {e}")
return None
@staticmethod
def cancel_order(order_id: int, api_url: str, api_key: str) -> Optional[str]:
url = f"{api_url}?action=cancel&order={order_id}&key={api_key}"
try:
response = requests.get(url)
response.raise_for_status()
cancel_status = response.json().get("cancel")
return cancel_status
except requests.exceptions.RequestException as ex:
logger.error(f"Error cancelling SocType order: {ex}")
return None
# --------------------------------------------------------
def checkbox(cardinal: Cardinal):
threading.Thread(target=process_orders, args=[cardinal]).start()
# Проверка статусов заказов
def process_orders(c: Cardinal):
while True:
logger.info("Проверка статусов заказов...")
api_url = get_api_url()
api_key = get_api_key()
def check_order_status(order_id: str) -> dict:
url = f"{api_url}?action=status&order={order_id}&key={api_key}"
try:
response = requests.get(url)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Ошибка при получении статуса заказа {order_id}: {e}")
return {}
def check_and_send_message(orders: dict, status: str, send_message_func):
orders_to_delete = []
for order_id, order_info in orders.items():
if order_info["status"] == status:
logger.info(f"Заказ {order_id} {status.lower()}!")
send_message_func(c, order_id)
orders_to_delete.append(order_id)
return orders_to_delete
def send_completion_message(c: Cardinal, order_id: str):
orders = load_orders()
chat_id = orders[order_id]["chat_id"]
message_text = f"✅ Заказ #{orders[order_id]['order_id']} выполнен!\nПожалуйста, перейдите по ссылке https://funpay.com/orders/{orders[order_id]['order_id']}/ и нажмите кнопку «Подтвердить выполнение заказа»."
try:
c.send_message(chat_id, message_text)
except Exception as e:
logger.error(f"{e}")
def send_canceled_message(c: Cardinal, order_id: str):
orders = load_orders()
chat_id = orders[order_id]["chat_id"]
message_text = f"❌ Заказ #{orders[order_id]['order_id']} отменён!"
try:
c.send_message(chat_id, message_text)
try:
c.account.refund(orders[order_id]['order_id'])
except Exception as e:
pass
except Exception as e:
logger.error(f"{e}")
def send_partial_message(c: Cardinal, order_id: str):
settings = load_settings()
orders = load_orders()
cashlist = load_cashlist()
chat_id = orders[order_id]["chat_id"]
partial_amount = int(orders[order_id].get('partial_amount', 0))
new_service_id = orders[order_id]['service_id']
new_link = orders[order_id]['order_url']
order_fid = orders[order_id]['order_id']
orderdatatime = orders[order_id]['orderdatetime']
try:
smm_order_id = SocTypeAPI.create_order(new_service_id, new_link, partial_amount, api_url, api_key)
if smm_order_id is not None:
if settings.get("set_recreated_order", False):
cashlist[smm_order_id] = {
"service_id": new_service_id,
"chat_id": chat_id,
"order_id": order_fid,
"order_url": new_link,
"order_amount": partial_amount,
"partial_amount": 0,
"orderdatetime": orderdatatime,
"status": "new"
}
save_cashlist(cashlist)
c.send_message(chat_id, f"""
📈 Ваш заказ #{order_fid} был пересоздан!
🆔 Новый ID заказа: {smm_order_id}
⏳ Остаток выполнения: {partial_amount}
""")
else:
c.send_message(chat_id, f"""
🔴 Заказ #{order_fid} был приостановлен!
⏳ Остаток выполнения: {partial_amount}
""")
except Exception as e:
logger.error(f"{e}")
orders = load_orders()
updated_orders = {}
for order_id, order_info in orders.items():
order_status = check_order_status(order_id)
if order_status:
updated_orders[order_id] = {
"service_id": order_info['service_id'],
"chat_id": order_info["chat_id"],
"order_id": order_info["order_id"],
"order_url": order_info['order_url'],
"order_amount": order_info['order_amount'],
"partial_amount": int(order_status.get("remains", 0)),
"orderdatetime": order_info['orderdatetime'],
"status": order_status.get("status", "unknown")
}
save_orders(updated_orders)
completed_orders = check_and_send_message(updated_orders, "Completed", send_completion_message)
canceled_orders = check_and_send_message(updated_orders, "Canceled", send_canceled_message)
partial_orders = check_and_send_message(updated_orders, "Partial", send_partial_message)
# удаление заказов после отправки сообщений
for order_id in completed_orders + canceled_orders + partial_orders:
if order_id in updated_orders:
del updated_orders[order_id]
save_orders(updated_orders)
# обновление списка orders с данными из cashlist
cashlist = load_cashlist()
for order_id, order_info in cashlist.items():
if order_id not in updated_orders:
updated_orders[order_id] = order_info
save_orders(updated_orders)
cashlist.clear()
save_cashlist(cashlist)
logger.info("Проверка статусов заказов завершена. Сплю минуту..")
time.sleep(60)
def init_commands(cardinal: Cardinal, *args):
# старт сообщение
settings = load_settings()
if settings.get("set_start_mess", False):
send_smm_start_info(cardinal)
if not cardinal.telegram:
return
tg = cardinal.telegram
bot = tg.bot
def send_smm_balance_command(m: types.Message):
text_balance = send_smm_balance_info(cardinal)
try:
bot.reply_to(m, text_balance, parse_mode='HTML')
except:
pass
settings_smm_keyboard = InlineKeyboardMarkup(row_width=1)
set_api = InlineKeyboardButton("🔗 API URL", callback_data='set_api')
set_api_key = InlineKeyboardButton("🔐 API KEY", callback_data='set_api_key')
set_api_2 = InlineKeyboardButton("🔗 API URL 2", callback_data='set_api_2')
set_api_key_2 = InlineKeyboardButton("🔐 API KEY 2", callback_data='set_api_key_2')
set_usersm_settings = InlineKeyboardButton("🛠 Настройки", callback_data='set_usersm_settings')
pay_orders = InlineKeyboardButton("📝 Оплаченные заказы", callback_data='pay_orders')
active_orders = InlineKeyboardButton("📋 Активные заказы", callback_data='active_orders')
settings_smm_keyboard.row(set_api, set_api_key)
settings_smm_keyboard.row(set_api_2, set_api_key_2)
settings_smm_keyboard.add(set_usersm_settings, pay_orders, active_orders)
def update_alerts_keyboard():
alerts_smm_keyboard = InlineKeyboardMarkup(row_width=1)
if settings.get("set_alert_neworder", False):
set_alert_neworder = InlineKeyboardButton("🔔 Увед. о созданом заказе", callback_data='set_alert_neworder')
else:
set_alert_neworder = InlineKeyboardButton("🔕 Увед. о созданом заказе", callback_data='set_alert_neworder')
if settings.get("set_alert_errororder", False):
set_alert_errororder = InlineKeyboardButton("🔔 Увед. при ошибке создания", callback_data='set_alert_errororder')
else:
set_alert_errororder = InlineKeyboardButton("🔕 Увед. при ошибке создания", callback_data='set_alert_errororder')
if settings.get("set_alert_smmbalance_new", False):
set_alert_smmbalance_new = InlineKeyboardButton("🔔 Увед. о балансе смм до создания", callback_data='set_alert_smmbalance_new')
else:
set_alert_smmbalance_new = InlineKeyboardButton("🔕 Увед. о балансе смм до создания", callback_data='set_alert_smmbalance_new')
if settings.get("set_alert_smmbalance", False):
set_alert_smmbalance = InlineKeyboardButton("🔔 Увед. о балансе смм после создания", callback_data='set_alert_smmbalance')
else:
set_alert_smmbalance = InlineKeyboardButton("🔕 Увед. о балансе смм после создания", callback_data='set_alert_smmbalance')
if settings.get("set_refund_smm", False):
set_refund_smm = InlineKeyboardButton("🟢 Автовозврат", callback_data='set_refund_smm')
else:
set_refund_smm = InlineKeyboardButton("🔴 Автовозврат", callback_data='set_refund_smm')
if settings.get("set_start_mess", False):
set_start_mess = InlineKeyboardButton("🟢 Сообщение при запуске FPC", callback_data='set_start_mess')
else:
set_start_mess = InlineKeyboardButton("🔴 Сообщение при запуске FPC", callback_data='set_start_mess')
if settings.get("set_tg_private", False):
set_tg_private = InlineKeyboardButton("🟢 Закрытые ТГ каналы/группы", callback_data='set_tg_private')
else:
set_tg_private = InlineKeyboardButton("🔴 Закрытые ТГ каналы/группы", callback_data='set_tg_private')
if settings.get("set_recreated_order", False):
set_recreated_order = InlineKeyboardButton("🟢 Пересоздание заказа", callback_data='set_recreated_order')
else:
set_recreated_order = InlineKeyboardButton("🔴 Пересоздание заказа", callback_data='set_recreated_order')
set_back_butt = InlineKeyboardButton("⬅️ Назад", callback_data='set_back_butt')
alerts_smm_keyboard.add(set_alert_neworder, set_alert_errororder, set_alert_smmbalance_new, set_alert_smmbalance, set_refund_smm, set_start_mess, set_tg_private, set_recreated_order, set_back_butt)
return alerts_smm_keyboard
def send_settings(m: types.Message):
bot.reply_to(m, "API 1: <code>ID:</code>\nAPI 2: <code>ID2:</code>\n\n⚙️ AutoSmm:", reply_markup=settings_smm_keyboard)
def edit(call: telebot.types.CallbackQuery):
text_sett_uss = f"🛠 Настройки:"
if call.data == 'set_usersm_settings':
bot.edit_message_text(
chat_id=call.message.chat.id,
message_id=call.message.message_id,
text=text_sett_uss,
reply_markup=update_alerts_keyboard()
)
# кнопки настроек
elif call.data == 'set_alert_neworder':
settings['set_alert_neworder'] = not settings['set_alert_neworder']
save_settings(settings)
new_markup = update_alerts_keyboard()
bot.edit_message_reply_markup(
chat_id=call.message.chat.id,
message_id=call.message.message_id,
reply_markup=new_markup
)
elif call.data == 'set_alert_errororder':
settings['set_alert_errororder'] = not settings['set_alert_errororder']
save_settings(settings)
new_markup = update_alerts_keyboard()
bot.edit_message_reply_markup(
chat_id=call.message.chat.id,
message_id=call.message.message_id,
reply_markup=new_markup
)
elif call.data == 'set_alert_smmbalance_new':
settings['set_alert_smmbalance_new'] = not settings['set_alert_smmbalance_new']
save_settings(settings)
new_markup = update_alerts_keyboard()
bot.edit_message_reply_markup(
chat_id=call.message.chat.id,
message_id=call.message.message_id,
reply_markup=new_markup
)
elif call.data == 'set_alert_smmbalance':
settings['set_alert_smmbalance'] = not settings['set_alert_smmbalance']
save_settings(settings)
new_markup = update_alerts_keyboard()
bot.edit_message_reply_markup(
chat_id=call.message.chat.id,
message_id=call.message.message_id,
reply_markup=new_markup
)
elif call.data == 'set_refund_smm':
settings['set_refund_smm'] = not settings['set_refund_smm']
save_settings(settings)
new_markup = update_alerts_keyboard()
bot.edit_message_reply_markup(
chat_id=call.message.chat.id,
message_id=call.message.message_id,
reply_markup=new_markup
)
elif call.data == 'set_start_mess':
settings['set_start_mess'] = not settings['set_start_mess']
save_settings(settings)
new_markup = update_alerts_keyboard()
bot.edit_message_reply_markup(
chat_id=call.message.chat.id,
message_id=call.message.message_id,
reply_markup=new_markup
)
elif call.data == 'set_auto_refill':
settings['set_auto_refill'] = not settings['set_auto_refill']
save_settings(settings)
new_markup = update_alerts_keyboard()
bot.edit_message_reply_markup(
chat_id=call.message.chat.id,
message_id=call.message.message_id,
reply_markup=new_markup
)
elif call.data == 'set_tg_private':
if 'set_tg_private' not in settings:
settings['set_tg_private'] = True
else:
settings['set_tg_private'] = not settings['set_tg_private']
save_settings(settings)
new_markup = update_alerts_keyboard()
bot.edit_message_reply_markup(
chat_id=call.message.chat.id,
message_id=call.message.message_id,
reply_markup=new_markup
)
elif call.data == 'set_recreated_order':
if 'set_recreated_order' not in settings:
settings['set_recreated_order'] = True
else:
settings['set_recreated_order'] = not settings['set_recreated_order']
save_settings(settings)
new_markup = update_alerts_keyboard()
bot.edit_message_reply_markup(
chat_id=call.message.chat.id,
message_id=call.message.message_id,
reply_markup=new_markup
)
elif call.data == 'set_back_butt':
bot.edit_message_text(
chat_id=call.message.chat.id,
message_id=call.message.message_id,
text="API 1: <code>ID:</code>\nAPI 2: <code>ID2:</code>\n\n⚙️ AutoSmm:",
reply_markup=settings_smm_keyboard
)
elif call.data == 'set_api':
back_button = InlineKeyboardButton("❌ Отмена", callback_data='delete_back_butt')
kb = InlineKeyboardMarkup().add(back_button)
current_value = settings.get('api_url', 'Не установлено')
result = bot.send_message(call.message.chat.id,
f'<b>Текущее значение URL: </b><span class="tg-spoiler">{current_value}</span>\n\n'
'<i>⬇️ Введите новое значение ⬇️</i>',
reply_markup=kb)
result = tg.set_state(
chat_id=call.message.chat.id,
message_id=result.id,
user_id=call.from_user.id,
state="setting_url"
)
elif call.data == 'set_api_key':
back_button = InlineKeyboardButton("❌ Отмена", callback_data='delete_back_butt')
kb = InlineKeyboardMarkup().add(back_button)
current_value = settings.get('api_key', 'Не установлен')
result = bot.send_message(call.message.chat.id,
f'<b>Текущее значение API KEY: </b><span class="tg-spoiler">{current_value}</span>\n\n'
'<i>⬇️ Введите новое значение ⬇️</i>',
reply_markup=kb)
result = tg.set_state(
chat_id=call.message.chat.id,
message_id=result.id,
user_id=call.from_user.id,
state="setting_api_key"
)
elif call.data == 'set_api_2':
back_button = InlineKeyboardButton("❌ Отмена", callback_data='delete_back_butt')
kb = InlineKeyboardMarkup().add(back_button)
current_value = settings.get('api_url_2', 'Не установлено')
result = bot.send_message(call.message.chat.id,
f'<b>Текущее значение URL 2: </b><span class="tg-spoiler">{current_value}</span>\n\n'
'<i>⬇️ Введите новое значение ⬇️</i>',
reply_markup=kb)
result = tg.set_state(
chat_id=call.message.chat.id,
message_id=result.id,
user_id=call.from_user.id,
state="setting_url_2"
)
elif call.data == 'set_api_key_2':
back_button = InlineKeyboardButton("❌ Отмена", callback_data='delete_back_butt')
kb = InlineKeyboardMarkup().add(back_button)
current_value = settings.get('api_key_2', 'Не установлен')
result = bot.send_message(call.message.chat.id,
f'<b>Текущее значение API KEY 2: </b><span class="tg-spoiler">{current_value}</span>\n\n'
'<i>⬇️ Введите новое значение ⬇️</i>',
reply_markup=kb)
result = tg.set_state(
chat_id=call.message.chat.id,
message_id=result.id,
user_id=call.from_user.id,
state="setting_api_key_2"
)
elif call.data == 'delete_back_butt':
bot.delete_message(call.message.chat.id, call.message.message_id)
tg.clear_state(call.message.chat.id, call.from_user.id)
elif call.data == 'pay_orders':
back_button = InlineKeyboardButton("⬅️ Назад", callback_data='delete_back_butt')
kb = InlineKeyboardMarkup().add(back_button)
orders_data = load_payorders()
if not orders_data:
orders_text = "📝 Оплаченные заказы отсутствуют."
bot.send_message(call.message.chat.id, orders_text, reply_markup=kb)
bot.answer_callback_query(call.id)
return
orders_text = "📝 Оплаченные заказы:\n\n"
for order in orders_data:
orders_text += f"🆔 ID заказа: {order['OrderID']}\n"
orders_text += f"⠀∟📋 Название: {order['Order']}\n"
orders_text += f"⠀∟🔢 Кол-во: {order['Amount']}\n"
orders_text += f"⠀∟👤 Покупатель: {order['buyer']}\n"
orders_text += f"⠀∟📅 Дата: {order['OrderDateTime']}\n"
orders_text += f"⠀∟🔗 Ссылка: {order['url']}\n\n"
bot.send_message(call.message.chat.id, orders_text, reply_markup=kb)
elif call.data == 'active_orders':
back_button = InlineKeyboardButton("⬅️ Назад", callback_data='delete_back_butt')
kb = InlineKeyboardMarkup().add(back_button)
orders_data = load_orders()
if not orders_data:
orders_text = "📋 Активные заказы отсутствуют."
bot.send_message(call.message.chat.id, orders_text, reply_markup=kb)
bot.answer_callback_query(call.id)
return
orders_text = "📋 Активные заказы:\n\n"
for order_id, order in orders_data.items():
orders_text += f"🆔 ID заказа: {order_id}\n"
orders_text += f"⠀∟🔢 Кол-во: {order['order_amount']}\n"
orders_text += f"⠀∟📅 Дата: {order['orderdatetime']}\n"
orders_text += f"⠀∟📋 Статус: {order['status']}\n\n"
bot.send_message(call.message.chat.id, orders_text, reply_markup=kb)
bot.answer_callback_query(call.id)
def handle_text_input(message: telebot.types.Message):
state_data = tg.get_state(message.chat.id, message.from_user.id)
if state_data and 'state' in state_data:
state = state_data['state']
if state == 'setting_url':
settings['api_url'] = message.text
save_settings(settings)
bot.send_message(message.from_user.id, f'✅ Успех: URL обновлён на: <span class="tg-spoiler">{message.text}</span>\n‼️ Напишите /restart')
bot.delete_message(message.chat.id, message.message_id)
bot.delete_message(message.chat.id, message.message_id - 1)
logger.info(f'URL обновлён на: {message.text}')
elif state == 'setting_api_key':
settings['api_key'] = message.text
save_settings(settings)
bot.send_message(message.from_user.id, f'✅ Успех: API KEY обновлён на: <span class="tg-spoiler">{message.text}</span>\n‼️ Напишите /restart')
bot.delete_message(message.chat.id, message.message_id)
bot.delete_message(message.chat.id, message.message_id - 1)
logger.info(f'API KEY обновлён на: {message.text}')
elif state == 'setting_url_2':
settings['api_url_2'] = message.text
save_settings(settings)
bot.send_message(message.from_user.id, f'✅ Успех: URL 2 обновлён на: <span class="tg-spoiler">{message.text}</span>\n‼️ Напишите /restart')
bot.delete_message(message.chat.id, message.message_id)
bot.delete_message(message.chat.id, message.message_id - 1)
logger.info(f'URL 2 обновлён на: {message.text}')
elif state == 'setting_api_key_2':
settings['api_key_2'] = message.text
save_settings(settings)
bot.send_message(message.from_user.id, f'✅ Успех: API KEY 2 обновлён на: <span class="tg-spoiler">{message.text}</span>\n‼️ Напишите /restart')
bot.delete_message(message.chat.id, message.message_id)
bot.delete_message(message.chat.id, message.message_id - 1)
logger.info(f'API KEY 2 обновлён на: {message.text}')
tg.clear_state(message.chat.id, message.from_user.id)
tg.cbq_handler(edit, lambda c: c.data in [
'set_api',
'set_api_key',
'set_api_2',
'set_api_key_2',
'set_usersm_settings',
'set_back_butt',
'set_alert_neworder',
'set_alert_errororder',
'set_alert_smmbalance_new',
'set_alert_smmbalance',
'set_refund_smm',
'set_auto_refill',
'set_start_mess',
'set_tg_private',
'pay_orders',
'active_orders',
'set_recreated_order',
'delete_back_butt'
])
tg.msg_handler(
handle_text_input,
func=lambda m: tg.check_state(m.chat.id, m.from_user.id, "setting_url") or
tg.check_state(m.chat.id, m.from_user.id, "setting_api_key") or
tg.check_state(m.chat.id, m.from_user.id, "setting_url_2") or
tg.check_state(m.chat.id, m.from_user.id, "setting_api_key_2")
)
tg.msg_handler(send_settings, commands=["autosmm"])
tg.msg_handler(send_smm_balance_command, commands=["check_balance"])
cardinal.add_telegram_commands(UUID, [
("autosmm", f"настройки {NAME}", True),
("check_balance", f"баланс {NAME}", True)
])
BIND_TO_PRE_INIT = [init_commands]
BIND_TO_POST_INIT = [checkbox]
BIND_TO_NEW_ORDER = [bind_to_new_order]
BIND_TO_NEW_MESSAGE = [msg_hook]
BIND_TO_DELETE = None