# -- version --
__version__ = (1, 0, 0)
# -- version --
# ███╗░░░███╗███████╗░█████╗░██████╗░░█████╗░░██╗░░░░░░░██╗░██████╗░██████╗
# ████╗░████║██╔════╝██╔══██╗██╔══██╗██╔══██╗░██║░░██╗░░██║██╔════╝██╔════╝
# ██╔████╔██║█████╗░░███████║██║░░██║██║░░██║░╚██╗████╗██╔╝╚█████╗░╚█████╗░
# ██║╚██╔╝██║██╔══╝░░██╔══██║██║░░██║██║░░██║░░████╔═████║░░╚═══██╗░╚═══██╗
# ██║░╚═╝░██║███████╗██║░░██║██████╔╝╚█████╔╝░░╚██╔╝░╚██╔╝░██████╔╝██████╔╝
# ╚═╝░░░░░╚═╝╚══════╝╚═╝░░╚═╝╚═════╝░░╚════╝░░░░╚═╝░░░╚═╝░░╚═════╝░╚═════╝░
# © Copyright 2025 (!!! НА ВСЕ МОДУЛИ ДЕЙСТВУЕТ ЛИЦЕНЗИЯ !!!)
# ✈ https://t.me/mead0wssMods
# meta developer: @mead0wssMods
# scope: heroku_only
import aiohttp
from .. import loader, utils
# флаги
COUNTRY_FLAGS = {
4: "🇦🇫", 8: "🇦🇱", 12: "🇩🇿", 16: "🇦🇸", 20: "🇦🇩", 24: "🇦🇴", 28: "🇦🇬", 32: "🇦🇷", 51: "🇦🇲",
52: "🇧🇧", 56: "🇧🇪", 68: "🇧🇴", 76: "🇧🇷", 84: "🇧🇿", 96: "🇧🇳", 100: "🇧🇬", 108: "🇧🇮", 112: "🇧🇾",
116: "🇰🇭", 120: "🇨🇲", 124: "🇨🇦", 136: "🇰🇾", 140: "🇨🇫", 148: "🇹🇩", 152: "🇨🇱", 156: "🇨🇳",
170: "🇨🇴", 174: "🇰🇲", 178: "🇨🇬", 180: "🇨🇩", 184: "🇨🇰", 188: "🇨🇷", 191: "🇭🇷", 192: "🇨🇺",
196: "🇨🇾", 203: "🇨🇿", 208: "🇩🇰", 212: "🇩🇲", 214: "🇩🇴", 218: "🇪🇨", 222: "🇸🇻", 231: "🇪🇹",
232: "🇪🇷", 233: "🇪🇪", 234: "🇫🇰", 238: "🇫🇯", 242: "🇫🇮", 246: "🇫🇷", 250: "🇫🇷", 254: "🇬🇫",
258: "🇵🇫", 260: "🇹🇫", 262: "🇩🇯", 266: "🇬🇦", 268: "🇬🇪", 270: "🇬🇲", 276: "🇩🇪", 288: "🇬🇭",
292: "🇬🇮", 300: "🇬🇷", 304: "🇬🇱", 308: "🇬🇩", 312: "🇬🇵", 316: "🇬🇺", 320: "🇬🇹", 324: "🇬🇳",
328: "🇬🇾", 332: "🇭🇹", 336: "🇻🇦", 340: "🇭🇳", 344: "🇭🇰", 348: "🇭🇺", 352: "🇮🇸", 356: "🇮🇳",
360: "🇮🇩", 364: "🇮🇷", 368: "🇮🇶", 372: "🇮🇪", 376: "🇮🇱", 380: "🇮🇹", 384: "🇨🇮", 388: "🇯🇲",
392: "🇯🇵", 400: "🇯🇴", 404: "🇰🇪", 408: "🇰🇵", 410: "🇰🇷", 414: "🇰🇼", 417: "🇰🇬", 418: "🇱🇦",
422: "🇱🇧", 426: "🇱🇸", 428: "🇱🇻", 430: "🇱🇷", 434: "🇱🇾", 438: "🇱🇮", 440: "🇱🇹", 442: "🇱🇺",
446: "🇲🇴", 450: "🇲🇬", 454: "🇲🇼", 458: "🇲🇾", 462: "🇲🇻", 466: "🇲🇱", 470: "🇲🇹", 474: "🇲🇶",
478: "🇲🇷", 480: "🇲🇺", 484: "🇲🇽", 492: "🇲🇨", 496: "🇲🇳", 498: "🇲🇩", 499: "🇲🇪", 504: "🇲🇦",
508: "🇲🇿", 512: "🇴🇲", 516: "🇳🇦", 520: "🇳🇷", 524: "🇳🇵", 528: "🇳🇱", 531: "🇨🇼", 533: "🇦🇼",
534: "🇸🇽", 540: "🇳🇨", 554: "🇳🇿", 558: "🇳🇮", 562: "🇳🇪", 566: "🇳🇬", 570: "🇳🇺", 574: "🇳🇫",
578: "🇳🇴", 580: "🇲🇵", 583: "🇫🇲", 584: "🇲🇭", 585: "🇵🇼", 586: "🇵🇰", 591: "🇵🇦", 598: "🇵🇬",
600: "🇵🇾", 604: "🇵🇪", 608: "🇵🇭", 612: "🇵🇳", 616: "🇵🇱", 620: "🇵🇹", 624: "🇬🇼", 626: "🇹🇱",
630: "🇵🇷", 634: "🇶🇦", 638: "🇷🇪", 642: "🇷🇴", 643: "🇷🇺", 646: "🇷🇼", 652: "🇧🇱", 654: "🇸🇭",
659: "🇰🇳", 662: "🇱🇨", 663: "🇲🇫", 666: "🇵🇲", 670: "🇻🇨", 674: "🇸🇲", 678: "🇸🇹", 682: "🇸🇦",
686: "🇸🇳", 688: "🇷🇸", 690: "🇸🇨", 694: "🇸🇱", 702: "🇸🇬", 703: "🇸🇰", 705: "🇸🇮", 706: "🇸🇴",
710: "🇿🇦", 716: "🇿🇼", 724: "🇪🇸", 736: "🇸🇩", 737: "🇸🇸", 740: "🇸🇷", 748: "🇸🇿", 752: "🇸🇪",
756: "🇨🇭", 760: "🇸🇾", 762: "🇹🇯", 764: "🇹🇭", 768: "🇹🇬", 772: "🇹🇰", 776: "🇹🇴", 780: "🇹🇹",
784: "🇦🇪", 788: "🇹🇳", 792: "🇹🇷", 795: "🇹🇲", 796: "🇹🇨", 798: "🇹🇻", 800: "🇺🇬", 804: "🇺🇦",
818: "🇪🇬", 826: "🇬🇧", 831: "🇬🇬", 832: "🇯🇪", 833: "🇮🇲", 840: "🇺🇸", 854: "🇧🇫", 858: "🇺🇾",
860: "🇺🇿", 862: "🇻🇪", 876: "🇼🇫", 882: "🇼🇸", 887: "🇾🇪", 894: "🇿🇲", 90: "🇸🇧", 92: "🇻🇬",
104: "🇲🇲", 132: "🇨🇻", 144: "🇱🇰", 162: "🇽🇰", 166: "🇨🇨",
}
@loader.tds
class DDNetStats(loader.Module):
"""Модуль для просмотра статистики игрока DDNet через ddstats.tw"""
strings = {
"name": "DDNetStats",
"no_args": "❌ Укажите ник игрока!",
"not_found": "❌ Игрок не найден или ошибка API.",
}
async def client_ready(self, client, db):
self.client = client
@loader.command()
async def ddstats(self, message):
"""<ник> — Показать статистику игрока DDNet"""
args = utils.get_args_raw(message)
if not args:
await utils.answer(message, self.strings["no_args"])
return
try:
async with aiohttp.ClientSession() as session:
async with session.get(f"https://ddstats.tw/player/json?player={args}") as resp:
if resp.status != 200:
await utils.answer(message, self.strings["not_found"])
return
data = await resp.json()
if "error" in data and data["error"] == "player not found":
await utils.answer(message, self.strings["not_found"])
return
response = ""
# профиль
profile_list = data.get("recent_player_info", [])
profile2 = data.get("profile", {})
if profile_list and profile2:
profile = profile_list[0]
name = profile.get("name", args)
points = profile2.get("points", "—")
clan = profile.get("clan", "—")
country_id = profile.get("country", -1)
flag = COUNTRY_FLAGS.get(country_id, "-")
skin = profile.get("skin_name", "—")
last_seen = profile.get("last_seen", "-")
response += (
f"👤 Игрок: {name}\n\n"
f"📌 Профиль:\n"
f"Поинты: {points}\n"
f"Клан: {clan}\n"
f"Флаг: {flag}\n"
f"Скин: {skin}\n"
f"Дата информации: {last_seen}\n"
"
\n"
)
# прогресс по категориям
completion = data.get("completion_progress", [])
if completion:
completion_str = []
for cat in completion:
category = cat.get("category", "Неизвестно")
finished = cat.get("maps_finished", 0)
total = cat.get("maps_total", 0)
completion_str.append(f"{category} - {finished}/{total}")
response += (
"📦 Прогресс по категориям:\n"
+ "\n".join(completion_str) +
"
\n\n"
)
# ласт активность
recent = data.get("recent_activity", [])
if recent:
recent_str = []
for act in recent:
date = act.get("date", "—")
map_name = act.get("map_name", "—")
hours = round(act.get("seconds_played", 0) / 60)
recent_str.append(f"{date} - {map_name} ({hours}мин.)")
response += (
"⏰️ Последняя активность:\n"
+ "\n".join(recent_str) +
"
\n\n"
)
# напарники
teammates = data.get("favourite_teammates", [])
if teammates:
teammates_str = []
for mate in teammates:
mate_name = mate.get("name", "—")
team_rank = mate.get("ranks_together", "—")
teammates_str.append(f"{mate_name} - {team_rank} (ранг)")
response += (
"👥 Любимые напарники:\n"
+ "\n".join(teammates_str) +
"
\n\n"
)
# карты
maps = data.get("most_played_maps", [])
if maps:
maps_str = []
for m in maps:
map_name = m.get("map_name", "-")
hours = round(m.get("seconds_played", 0) / 3600)
maps_str.append(f"{map_name} - {hours}ч")
response += (
"🗺Карты:\n"
+ "\n".join(maps_str) +
"
\n\n"
)
# режимы
gametypes = data.get("most_played_gametypes", [])
if gametypes:
gametypes_str = []
for gt in gametypes:
key = gt.get("key", "—")
hours = round(gt.get("seconds_played", 0) / 3600)
gametypes_str.append(f"{key} - {hours}ч")
response += (
"🎯Режимы:\n"
+ "\n".join(gametypes_str) +
"
\n\n"
)
# вся активность
general = data.get("general_activity", {})
if general:
total_hours = round(general.get("total_seconds_played", 0) / 3600)
avg_hours = round(general.get("average_seconds_played", 0) / 3600)
start_date = general.get("start_of_playtime", "—")
response += (
"📈 Общая активность:\n"
f"Общее время: {total_hours}ч\n"
f"Среднее время игры: {avg_hours}ч\n"
f"Начал играть: {start_date}"
"
"
)
await utils.answer(message, response)
except Exception as e:
await utils.answer(message, f"❌ Ошибка: {str(e)}")
@loader.command()
async def ddstatsred(self, message):
"""<ник> - Упрощенная версия"""
args = utils.get_args_raw(message)
if not args:
await utils.answer(message, self.strings["no_args"])
return
try:
async with aiohttp.ClientSession() as session:
async with session.get(f"https://ddstats.tw/player/json?player={args}") as resp:
if resp.status != 200:
await utils.answer(message, self.strings["not_found"])
return
data = await resp.json()
if "error" in data and data["error"] == "player not found":
await utils.answer(message, self.strings["not_found"])
return
response = ""
# профиль
profile_list = data.get("recent_player_info", [])
profile2 = data.get("profile", {})
if profile_list and profile2:
profile = profile_list[0]
name = profile.get("name", args)
points = profile2.get("points", "—")
clan = profile.get("clan", "—")
country_id = profile.get("country", -1)
flag = COUNTRY_FLAGS.get(country_id, "-")
skin = profile.get("skin_name", "—")
last_seen = profile.get("last_seen", "-")
response += (
f"👤 Игрок: {name}\n\n"
f"📌 Профиль:\n"
f"Поинты: {points}\n"
f"Клан: {clan}\n"
f"Флаг: {flag}\n"
f"Скин: {skin}\n"
f"Дата информации: {last_seen}\n"
"
\n"
)
# вся активность
general = data.get("general_activity", {})
if general:
total_hours = round(general.get("total_seconds_played", 0) / 3600)
avg_hours = round(general.get("average_seconds_played", 0) / 3600)
start_date = general.get("start_of_playtime", "—")
response += (
"📈 Общая активность:\n"
f"Общее время: {total_hours}ч\n"
f"Среднее время игры: {avg_hours}ч\n"
f"Начал играть: {start_date}"
"
"
)
await utils.answer(message, response)
except Exception as e:
await utils.answer(message, f"❌ Ошибка: {str(e)}")