forked from FOSS/ASF-Control-Bot
198 lines
7.2 KiB
Python
198 lines
7.2 KiB
Python
import asyncio
|
|
import re
|
|
|
|
from bot.logging_utils import get_logger
|
|
from bot.api.asf import get_all_bots, redeem_key
|
|
|
|
KEY_PATTERN = r"[A-Z0-9]{5}(?:-[A-Z0-9]{5}){2}"
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
def extract_keys(text: str) -> list[str]:
|
|
keys = re.findall(KEY_PATTERN, text.upper())
|
|
unique_keys = list(dict.fromkeys(keys))
|
|
logger.info("Из текста извлечены ключи: count=%s", len(unique_keys))
|
|
return unique_keys
|
|
|
|
|
|
def parse_redeem_result(result: str, bot_name: str | None = None) -> str:
|
|
result_lower = result.lower()
|
|
if bot_name:
|
|
for line in result.splitlines():
|
|
if f"<{bot_name.lower()}>" in line.lower():
|
|
result_lower = line.lower()
|
|
break
|
|
|
|
if "ok/nodetail" in result_lower or "ok/" in result_lower:
|
|
return "success"
|
|
if "ratelimited" in result_lower:
|
|
return "rate_limited"
|
|
if "alreadypurchased" in result_lower or "already purchased" in result_lower:
|
|
return "already_owned"
|
|
if "duplicateactivationcode" in result_lower:
|
|
return "duplicate"
|
|
if "regionlocked" in result_lower:
|
|
return "region_locked"
|
|
if "invalidactivationcode" in result_lower or "invalid" in result_lower:
|
|
return "invalid"
|
|
return "unknown"
|
|
|
|
|
|
async def redeem_single_bot_keys(bot_name: str, keys: list[str]) -> str:
|
|
logger.info(
|
|
"Начата активация ключей для одного бота: bot=%s count=%s",
|
|
bot_name,
|
|
len(keys),
|
|
)
|
|
success_count = 0
|
|
failed_count = 0
|
|
results = []
|
|
|
|
for key in keys:
|
|
logger.info(
|
|
"Попытка активации ключа для одного бота: bot=%s key=%s",
|
|
bot_name,
|
|
key,
|
|
)
|
|
success, result = await redeem_key(bot_name, key)
|
|
await asyncio.sleep(2)
|
|
|
|
if not success or not result:
|
|
failed_count += 1
|
|
logger.warning(
|
|
"Активация ключа завершилась ошибкой ASF/HTTP: bot=%s key=%s",
|
|
bot_name,
|
|
key,
|
|
)
|
|
results.append(f"❌ {key}: ошибка ASF")
|
|
continue
|
|
|
|
status = parse_redeem_result(result)
|
|
logger.info(
|
|
"Получен результат активации ключа: bot=%s key=%s status=%s",
|
|
bot_name,
|
|
key,
|
|
status,
|
|
)
|
|
|
|
if status == "success":
|
|
success_count += 1
|
|
results.append(f"✅ {key}: активировано")
|
|
elif status == "rate_limited":
|
|
failed_count += 1
|
|
results.append(f"⏳ {key}: лимит запросов")
|
|
elif status == "already_owned":
|
|
failed_count += 1
|
|
results.append(f"⚠️ {key}: игра уже есть")
|
|
elif status == "duplicate":
|
|
failed_count += 1
|
|
results.append(f"❌ {key}: ключ уже использован")
|
|
elif status == "region_locked":
|
|
failed_count += 1
|
|
results.append(f"🌍 {key}: регион лок")
|
|
elif status == "invalid":
|
|
failed_count += 1
|
|
results.append(f"❌ {key}: неверный ключ")
|
|
else:
|
|
failed_count += 1
|
|
results.append(f"❔ {key}: неизвестный ответ")
|
|
|
|
text = (
|
|
f"Результат активации для <code>{bot_name}</code>\n\n"
|
|
f"✅ Успешно: {success_count}\n"
|
|
f"❌ Ошибок: {failed_count}\n\n" + "\n".join(results[:50])
|
|
)
|
|
logger.info(
|
|
"Завершена активация ключей для одного бота: bot=%s success=%s failed=%s",
|
|
bot_name,
|
|
success_count,
|
|
failed_count,
|
|
)
|
|
return text[:4000] + ("\n\n...обрезано" if len(text) > 4000 else "")
|
|
|
|
|
|
async def redeem_all_bots_keys(keys: list[str], allowed_bots: list[str] | None = None) -> str:
|
|
logger.info("Начата активация ключей по всем ботам: count=%s", len(keys))
|
|
response = get_all_bots()
|
|
data = response.json()
|
|
available = list(data.get("Result", {}).keys())
|
|
bots = [name for name in available if allowed_bots is None or name in allowed_bots]
|
|
logger.info("Для массовой активации найдено ботов: count=%s", len(bots))
|
|
success_count = 0
|
|
failed_count = 0
|
|
results = []
|
|
|
|
for key in keys:
|
|
activated = False
|
|
key_report = []
|
|
logger.info("Начата обработка ключа по всем ботам: key=%s", key)
|
|
|
|
for bot_name in bots:
|
|
logger.info(
|
|
"Попытка активации ключа на боте: bot=%s key=%s",
|
|
bot_name,
|
|
key,
|
|
)
|
|
success, result = await redeem_key(bot_name, key)
|
|
await asyncio.sleep(2)
|
|
|
|
if not success or not result:
|
|
logger.warning(
|
|
"Активация ключа завершилась ошибкой ASF/HTTP: bot=%s key=%s",
|
|
bot_name,
|
|
key,
|
|
)
|
|
key_report.append(f"❌ {bot_name}: ошибка ASF")
|
|
continue
|
|
|
|
status = parse_redeem_result(result, bot_name)
|
|
logger.info(
|
|
"Получен результат активации ключа: bot=%s key=%s status=%s",
|
|
bot_name,
|
|
key,
|
|
status,
|
|
)
|
|
|
|
if status == "success":
|
|
key_report.append(f"✅ {bot_name}: активировано")
|
|
success_count += 1
|
|
activated = True
|
|
break
|
|
if status == "rate_limited":
|
|
key_report.append(f"⏳ {bot_name}: лимит запросов")
|
|
continue
|
|
if status == "already_owned":
|
|
key_report.append(f"⚠️ {bot_name}: игра уже есть")
|
|
continue
|
|
if status == "duplicate":
|
|
key_report.append(f"❌ {bot_name}: ключ уже использован")
|
|
break
|
|
if status == "region_locked":
|
|
key_report.append(f"🌍 {bot_name}: регион лок")
|
|
continue
|
|
if status == "invalid":
|
|
key_report.append(f"❌ {bot_name}: неверный ключ")
|
|
break
|
|
key_report.append(f"❔ {bot_name}: неизвестный ответ")
|
|
|
|
if not activated:
|
|
failed_count += 1
|
|
logger.warning(
|
|
"Ключ не удалось активировать ни на одном боте: key=%s",
|
|
key,
|
|
)
|
|
|
|
results.append(f"\n🔑 {key}\n" + "\n".join(key_report))
|
|
|
|
text = (
|
|
"Результат активации\n\n"
|
|
f"✅ Успешно: {success_count}\n"
|
|
f"❌ Ошибок: {failed_count}\n\n" + "\n".join(results[:50])
|
|
)
|
|
logger.info(
|
|
"Завершена массовая активация ключей: success=%s failed=%s",
|
|
success_count,
|
|
failed_count,
|
|
)
|
|
return text[:4000] + ("\n\n...обрезано" if len(text) > 4000 else "")
|