Files
limoka/Fixyres/FModules/BSR.py
2026-05-31 02:47:16 +00:00

256 lines
11 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

__version__ = (1, 0, 0)
# ©️ Fixyres, 2026-2030
# 🌐 https://github.com/Fixyres/FModules
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# 🔑 http://www.apache.org/licenses/LICENSE-2.0
# meta banner: https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/BSR/banner.png
# meta developer: @NFModules
# meta fhsdesc: brawlstars, game, funny
from .. import loader, utils
from urllib.parse import urlparse, parse_qs
async def extract_code(value: str) -> str:
if value.startswith("http"):
tags = parse_qs(urlparse(value).query).get("tag")
return tags[0] if tags else value
return value
async def to_id(code: str) -> int:
code = code.strip().upper()
if not code.startswith("X"):
return 0
val = 0
for ch in code[1:]:
i = "QWERTYUPASDFGHJKLZCVBNM23456789".find(ch)
if i == -1:
return 0
val = val * 31 + i
return val >> 8
async def to_code(n: int) -> str:
if n < 0:
return "X"
n_shifted = n << 8
res = []
chars = "QWERTYUPASDFGHJKLZCVBNM23456789"
while n_shifted > 0:
res.append(chars[n_shifted % 31])
n_shifted //= 31
return "X" + "".join(reversed(res))
@loader.tds
class BSR(loader.Module):
'''Module for finding nearby game rooms in BrawlStars.'''
strings = {
"name": "BSR",
"invalid_args": "<b>Usage:</b> <code>{prefix}bsr (room code/link) (previous) (next)</code>",
"invalid_code": "<b>Invalid room code!</b>",
"at_least_one": "<b>At least one argument (previous or next) must be greater than 0!</b>",
"prev_block": "<b>Previous:</b>\n<blockquote expandable>{prev_list}</blockquote>",
"next_block": "<b>Next:</b>\n<blockquote expandable>{next_list}</blockquote>",
"btn_target": "Target Room"
}
strings_ru = {
"_cls_doc": "Модуль для поиска ближайших игровых комнат в BrawlStars.",
"invalid_args": "<b>Использование:</b> <code>{prefix}bsr (код комнаты/ссылка) (предыдущие) (следующие)</code>",
"invalid_code": "<b>Неверный код комнаты!</b>",
"at_least_one": "<b>Хотя бы один аргумент (предыдущие или следующие) должен быть больше 0!</b>",
"prev_block": "<b>Предыдущие:</b>\n<blockquote expandable>{prev_list}</blockquote>",
"next_block": "<b>Следующие:</b>\n<blockquote expandable>{next_list}</blockquote>",
"btn_target": "Целевая комната"
}
strings_ua = {
"_cls_doc": "Модуль для пошуку найближчих ігрових кімнат у BrawlStars.",
"invalid_args": "<b>Використання:</b> <code>{prefix}bsr (код кімнати/посилання) (попередні) (наступні)</code>",
"invalid_code": "<b>Невірний код кімнати!</b>",
"at_least_one": "<b>Хоча б один аргумент (попередні або наступні) повинен бути більшим за 0!</b>",
"prev_block": "<b>Попередні:</b>\n<blockquote expandable>{prev_list}</blockquote>",
"next_block": "<b>Наступні:</b>\n<blockquote expandable>{next_list}</blockquote>",
"btn_target": "Цільова кімната"
}
strings_kz = {
"_cls_doc": "BrawlStars ойынында жақын маңдағы ойын бөлмелерін табуға арналған модуль.",
"invalid_args": "<b>Қолдану:</b> <code>{prefix}bsr (бөлме коды/сілтеме) (алдыңғы) (келесі)</code>",
"invalid_code": "<b>Қате бөлме коды!</b>",
"at_least_one": "<b>Кем дегенде бір аргумент (алдыңғы немесе келесі) 0-ден үлкен болуы керек!</b>",
"prev_block": "<b>Алдыңғы:</b>\n<blockquote expandable>{prev_list}</blockquote>",
"next_block": "<b>Келесі:</b>\n<blockquote expandable>{next_list}</blockquote>",
"btn_target": "Мақсатты бөлме"
}
strings_uz = {
"_cls_doc": "BrawlStars'da eng yaqin o'yin xonalarini topish uchun modul.",
"invalid_args": "<b>Qo'llanilishi:</b> <code>{prefix}bsr (xona kodi/havolasi) (oldingi) (keyingi)</code>",
"invalid_code": "<b>Noto'g'ri xona kodi!</b>",
"at_least_one": "<b>Kamida bitta argument (oldingi yoki keyingi) 0 dan katta bo'lishi kerak!</b>",
"prev_block": "<b>Oldingi:</b>\n<blockquote expandable>{prev_list}</blockquote>",
"next_block": "<b>Keyingi:</b>\n<blockquote expandable>{next_list}</blockquote>",
"btn_target": "Maqsadli xona"
}
strings_fr = {
"_cls_doc": "Module pour trouver des salles de jeu à proximité dans BrawlStars.",
"invalid_args": "<b>Utilisation:</b> <code>{prefix}bsr (code/lien) (précédents) (suivants)</code>",
"invalid_code": "<b>Code de salle invalide!</b>",
"at_least_one": "<b>Au moins un argument doit être supérieur à 0 !</b>",
"prev_block": "<b>Précédents:</b>\n<blockquote expandable>{prev_list}</blockquote>",
"next_block": "<b>Suivants:</b>\n<blockquote expandable>{next_list}</blockquote>",
"btn_target": "Salle cible"
}
strings_de = {
"_cls_doc": "Modul zum Finden von nahegelegenen Spielräumen in BrawlStars.",
"invalid_args": "<b>Verwendung:</b> <code>{prefix}bsr (Raumcode/Link) (vorherige) (nächste)</code>",
"invalid_code": "<b>Ungültiger Raumcode!</b>",
"at_least_one": "<b>Mindestens ein argument muss größer als 0 sein!</b>",
"prev_block": "<b>Vorherige:</b>\n<blockquote expandable>{prev_list}</blockquote>",
"next_block": "<b>Nächste:</b>\n<blockquote expandable>{next_list}</blockquote>",
"btn_target": "Zielraum"
}
strings_jp = {
"_cls_doc": "BrawlStarsで近くのゲームルームを検索するためのモジュール。",
"invalid_args": "<b>使用法:</b> <code>{prefix}bsr (コード/リンク) (前) (次)</code>",
"invalid_code": "<b>無効なルームコード!</b>",
"at_least_one": "<b>少なくとも1つの引数は0より大きくなければなりません</b>",
"prev_block": "<b>前:</b>\n<blockquote expandable>{prev_list}</blockquote>",
"next_block": "<b>次:</b>\n<blockquote expandable>{next_list}</blockquote>",
"btn_target": "ターゲットルーム"
}
@loader.command(
ru_doc="(код комнаты/ссылка) (предыдущие) (следующие) - найти комнаты.",
ua_doc="(код кімнати/посилання) (попередні) (наступні) - знайти кімнати.",
kz_doc="(бөлме коды/сілтеме) (алдыңғы) (келесі) - бөлмелерді табу.",
uz_doc="(xona kodi/havolasi) (oldingi) (keyingi) - xonalarni topish.",
fr_doc="(code/lien) (précédents) (suivants) - trouver des salles.",
de_doc="(Raumcode/Link) (vorherige) (nächste) - Räume finden.",
jp_doc="(コード/リンク) (前) (次) - ルームを検索します。"
)
async def bsr(self, message):
'''(room code/link) (previous) (next) - find rooms.'''
args = utils.get_args_raw(message).split()
if not args:
return await utils.answer(message, self.strings["invalid_args"].format(prefix=self.get_prefix()))
raw_input = args[0]
before = 0
nxt = 10
if len(args) >= 2:
try:
before = int(args[1])
except ValueError:
pass
if len(args) >= 3:
try:
nxt = int(args[2])
except ValueError:
pass
before = max(0, min(before, 5000))
nxt = max(0, min(nxt, 5000))
if before == 0 and nxt == 0:
return await utils.answer(message, self.strings["at_least_one"])
clean_tag = await extract_code(raw_input)
base_id = await to_id(clean_tag)
if base_id == 0:
return await utils.answer(message, self.strings["invalid_code"])
text, page, total_pages = await self.get_page_content(base_id, before, nxt, 0)
kb = self.build_keyboard(base_id, before, nxt, page, total_pages, clean_tag)
await self.inline.form(
message=message,
text=text,
photo="https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/BSR/banner.png",
reply_markup=kb
)
async def get_page_content(self, base_id: int, before: int, nxt: int, page: int):
actual_before = min(before, base_id)
total_pages = max(1, (actual_before + 9) // 10, (nxt + 9) // 10)
if page < 0:
page = total_pages - 1
if page >= total_pages:
page = 0
start = page * 10
prev_list = []
for i in range(start + 1, min(start + 10, actual_before) + 1):
c = await to_code(base_id - i)
link = f'<a href="https://link.brawlstars.com/invite/gameroom/en?tag={c}">{c}</a>'
prev_list.append(link)
next_list = []
for i in range(start + 1, min(start + 10, nxt) + 1):
c = await to_code(base_id + i)
link = f'<a href="https://link.brawlstars.com/invite/gameroom/en?tag={c}">{c}</a>'
next_list.append(link)
blocks = []
if prev_list:
blocks.append(self.strings["prev_block"].format(prev_list="\n".join(prev_list)))
if next_list:
blocks.append(self.strings["next_block"].format(next_list="\n".join(next_list)))
res = "\n\n".join(blocks)
if not res.strip():
res = " "
return res, page, total_pages
def build_keyboard(self, base_id: int, before: int, nxt: int, page: int, total_pages: int, clean_tag: str):
kb = [
[
{
"text": self.strings["btn_target"],
"copy": clean_tag
}
]
]
if total_pages > 1:
nav_row = []
if page > 0:
nav_row.append({"text": "", "callback": self.page_cb, "args": (base_id, before, nxt, page - 1, clean_tag)})
nav_row.append({"text": f"{page + 1} / {total_pages}", "callback": self.dummy_cb, "args": ()})
if page < total_pages - 1:
nav_row.append({"text": "", "callback": self.page_cb, "args": (base_id, before, nxt, page + 1, clean_tag)})
kb.append(nav_row)
return kb
async def dummy_cb(self, call):
await call.answer()
async def page_cb(self, call, base_id: int, before: int, nxt: int, page: int, clean_tag: str):
text, new_page, total_pages = await self.get_page_content(base_id, before, nxt, page)
kb = self.build_keyboard(base_id, before, nxt, new_page, total_pages, clean_tag)
await call.edit(
text=text,
photo="https://raw.githubusercontent.com/Fixyres/FModules/refs/heads/main/assets/BSR/banner.png",
reply_markup=kb
)