diff --git a/bot/cogs/authentication.py b/bot/cogs/authentication.py index d289afb..1c511cd 100644 --- a/bot/cogs/authentication.py +++ b/bot/cogs/authentication.py @@ -650,7 +650,7 @@ def timeout_feedback_embed() -> discord.Embed: @commands.dm_only() @commands.cooldown(60, 0, commands.BucketType.user) - @commands.command(aliases=["role", "membro"]) + @commands.hybrid_command(name="aplicar", aliases=["role", "membro", "aplicar_role"]) async def aplicar_role(self, ctx: Context): self.logger.info(f"[{ctx.author}] Autenticação iniciada.") diff --git a/bot/cogs/chat.py b/bot/cogs/chat.py index 4b7c4bc..d5720b0 100644 --- a/bot/cogs/chat.py +++ b/bot/cogs/chat.py @@ -120,8 +120,8 @@ async def get_price(item_id: int): @commands.check(is_authenticated) @commands.guild_only() @commands.cooldown(1, 60, commands.BucketType.user) - @commands.command("raids", aliases=["aplicar_raids"]) - async def aplicar_raids(self, ctx: Context): + @commands.command("raids", aliases=["aplicar_raids"]) + async def aplicar_raids(self, ctx: Context): denied_message = "Fool! Você já tem permissão para ir Raids!" if has_any_role(ctx.author, self.bot.setting.role.get("raids")): return await ctx.send(denied_message) diff --git a/bot/cogs/clan.py b/bot/cogs/clan.py index a7e6a66..4c89ae4 100644 --- a/bot/cogs/clan.py +++ b/bot/cogs/clan.py @@ -110,8 +110,11 @@ async def clan_user_info(self, ctx: Context, *, username: str): @commands.cooldown(1, 5, commands.BucketType.user) @commands.bot_has_permissions(embed_links=True) - @commands.command(aliases=["ranksupdate", "upranks", "rank"]) + @commands.hybrid_command(aliases=["ranksupdate", "upranks", "rank"]) async def ranks(self, ctx: Context, *, clan: str = "Atlantis"): + if getattr(ctx, "interaction", None) is None: + await ctx.send("Dica: use o comando de barra `/ranks` para uma melhor experiência.") + if clan.lower() == "atlantis argus": return await ctx.send("`!rank argus` irmão") elif clan.lower() == "atlantis": diff --git a/tests/helpers.py b/tests/helpers.py index 71ca65d..0e6ba6b 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -15,6 +15,28 @@ def _stub_modules(): stub_rs3clans = types.ModuleType("rs3clans") + + stub_django_models = types.ModuleType("django.db.models") + + class Q: + def __init__(self, *_args, **_kwargs): + pass + + stub_django_models.Q = Q + sys.modules["django.db.models"] = stub_django_models + + stub_api_models = types.ModuleType("atlantisbot_api.models") + + class DiscordUser: + objects = SimpleNamespace(filter=lambda **_kwargs: SimpleNamespace(first=lambda: None)) + + class DiscordIngameName: + pass + + stub_api_models.DiscordUser = DiscordUser + stub_api_models.DiscordIngameName = DiscordIngameName + sys.modules["atlantisbot_api.models"] = stub_api_models + stub_rs3clans.Clan = object stub_rs3clans.Player = object sys.modules["rs3clans"] = stub_rs3clans @@ -29,11 +51,20 @@ class Bot: stub_tools = types.ModuleType("bot.utils.tools") stub_tools.right_arrow = "->" + stub_tools.separator = "---" def has_any_role(*_args, **_kwargs): return False + async def get_clan_async(*_args, **_kwargs): + return [] + + def divide_list(value, *_args, **_kwargs): + return [value] + stub_tools.has_any_role = has_any_role + stub_tools.get_clan_async = get_clan_async + stub_tools.divide_list = divide_list sys.modules["bot.utils.tools"] = stub_tools stub_checks = types.ModuleType("bot.utils.checks") @@ -64,12 +95,46 @@ async def time_till_raids(): stub_raids.time_till_raids = time_till_raids sys.modules["bot.cogs.raids"] = stub_raids + stub_rsworld = types.ModuleType("bot.cogs.rsworld") + + async def grab_world(*_args, **_kwargs): + return None + + async def get_world(*_args, **_kwargs): + return None + + def random_world(*_args, **_kwargs): + return 1 + + def filtered_worlds(*_args, **_kwargs): + return [] + + stub_rsworld.grab_world = grab_world + stub_rsworld.get_world = get_world + stub_rsworld.random_world = random_world + stub_rsworld.filtered_worlds = filtered_worlds + sys.modules["bot.cogs.rsworld"] = stub_rsworld + + stub_roles = types.ModuleType("bot.utils.roles") + + async def check_admin_roles(*_args, **_kwargs): + return None + + async def check_exp_roles(*_args, **_kwargs): + return None + + stub_roles.check_admin_roles = check_admin_roles + stub_roles.check_exp_roles = check_exp_roles + sys.modules["bot.utils.roles"] = stub_roles + + @dataclass class FakeSettings: clan_name: str = "Atlantis" banner_image: str = "https://example.com/banner.png" prefix: str = "!" + mode: str = "dev" role: dict[str, int] | None = None chat: dict[str, int] | None = None @@ -84,11 +149,14 @@ class FakeContext: def __init__(self): self.sent_embed = None self.sent_content = None + self.sent_messages = [] self.author = SimpleNamespace(roles=[]) + self.interaction = None async def send(self, content=None, *, embed=None): self.sent_embed = embed self.sent_content = content + self.sent_messages.append({"content": content, "embed": embed}) def make_chat(): @@ -103,3 +171,27 @@ def run_async(coro: Any): import asyncio return asyncio.run(coro) + + +def make_clan(): + _stub_modules() + from bot.cogs.clan import Clan # noqa: E402 + + clan_settings = { + "Recruit": {"Emoji": "R", "Translation": "Recruta"}, + "Corporal": {"Emoji": "C", "Translation": "Cabo"}, + "Sergeant": {"Emoji": "S", "Translation": "Sargento"}, + "Lieutenant": {"Emoji": "L", "Translation": "Tenente"}, + "Captain": {"Emoji": "CP", "Translation": "Capitão"}, + "General": {"Emoji": "G", "Translation": "General"}, + } + fake_bot = SimpleNamespace(setting=SimpleNamespace(clan_settings=clan_settings)) + return Clan(fake_bot) + + +def make_authentication(): + _stub_modules() + from bot.cogs.authentication import UserAuthentication # noqa: E402 + + fake_bot = SimpleNamespace(setting=FakeSettings()) + return UserAuthentication(fake_bot) diff --git a/tests/test_aplicar_command.py b/tests/test_aplicar_command.py new file mode 100644 index 0000000..e6b8970 --- /dev/null +++ b/tests/test_aplicar_command.py @@ -0,0 +1,12 @@ +from discord.ext import commands + +from tests.helpers import make_authentication + + +def test_aplicar_role_is_hybrid_command(): + authentication = make_authentication() + command = authentication.aplicar_role + + assert isinstance(command, commands.HybridCommand) + assert command.name == "aplicar" + assert "membro" in command.aliases diff --git a/tests/test_ranks_command.py b/tests/test_ranks_command.py new file mode 100644 index 0000000..208b16f --- /dev/null +++ b/tests/test_ranks_command.py @@ -0,0 +1,29 @@ +from types import SimpleNamespace + +from discord.ext import commands + +from tests.helpers import FakeContext, make_clan, run_async + + +def test_ranks_is_hybrid_command(): + clan = make_clan() + + command = clan.ranks + assert isinstance(command, commands.HybridCommand) + assert command.name == "ranks" + assert "rank" in command.aliases + + +def test_ranks_prefix_suggests_slash(monkeypatch): + clan_cog = make_clan() + ctx = FakeContext() + + member = SimpleNamespace(exp=1, rank="Recruit", name="Test") + + monkeypatch.setattr("bot.cogs.clan.rs3clans.Clan", lambda *_args, **_kwargs: [member]) + + run_async(clan_cog.ranks.callback(clan_cog, ctx, clan="Atlantis")) + + assert len(ctx.sent_messages) == 2 + assert "use o comando de barra `/ranks`" in ctx.sent_messages[0]["content"] + assert ctx.sent_messages[1]["embed"] is not None