Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions bot/cogs/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from sentry_sdk import capture_exception

import discord
from discord import app_commands
from discord.ext import commands
from atlantisbot_api.models import (
AmigoSecretoState,
Expand All @@ -27,6 +28,29 @@
from bot.bot_client import Bot
from bot.utils.tools import separator, has_any_role
from bot.utils.context import Context
from bot.utils.checks import is_pedim_or_nriver


class SpamConfirmView(discord.ui.View):
def __init__(self, author_id: int):
super().__init__(timeout=120)
self.author_id = author_id
self.confirmed: bool | None = None

async def interaction_check(self, interaction: discord.Interaction) -> bool:
return interaction.user.id == self.author_id

@discord.ui.button(label="Sim, enviar para todos", style=discord.ButtonStyle.danger)
async def confirm(self, interaction: discord.Interaction, button: discord.ui.Button):
self.confirmed = True
self.stop()
await interaction.response.defer()

@discord.ui.button(label="Cancelar", style=discord.ButtonStyle.secondary)
async def cancel(self, interaction: discord.Interaction, button: discord.ui.Button):
self.confirmed = False
self.stop()
await interaction.response.edit_message(content="Cancelado.", view=None)


class Admin(commands.Cog):
Expand Down Expand Up @@ -535,6 +559,80 @@ def toggle_advlog_messages():
state.save()
return state.active

@commands.is_owner()
@commands.command(hidden=True)
async def sync(self, ctx: Context):
"""Syncs slash commands to Discord."""
await self.bot.tree.sync()
await ctx.send("Slash commands sincronizados com sucesso.")

@app_commands.check(is_pedim_or_nriver)
@app_commands.command(name="atl-spam", description="Envia uma mensagem no privado para todos os membros do servidor")
async def atl_spam(self, interaction: discord.Interaction, message: str, image: discord.Attachment | None = None):
image_data: bytes | None = None
if image:
image_data = await image.read()

def make_file() -> discord.File | None:
if image_data is None:
return None
return discord.File(io.BytesIO(image_data), filename=image.filename)

try:
file = make_file()
send_kwargs = {"file": file} if file else {}
await interaction.user.send(f"**[TESTE - Pré-visualização da mensagem]**\n\n{message}", **send_kwargs)
except discord.Forbidden:
return await interaction.response.send_message(
"Não foi possível enviar uma mensagem de teste para você. Verifique se suas DMs estão abertas.",
ephemeral=True,
)

view = SpamConfirmView(interaction.user.id)
await interaction.response.send_message(
"Mensagem de teste enviada no seu privado. Deseja enviá-la para **todos os membros** do servidor?",
view=view,
ephemeral=True,
)

await view.wait()

if not view.confirmed:
if view.confirmed is None:
await interaction.edit_original_response(content="Tempo esgotado. Envio cancelado.", view=None)
return

guild = self.bot.get_guild(self.bot.setting.server_id)
if not guild:
return await interaction.edit_original_response(content="Servidor não encontrado.", view=None)

await interaction.edit_original_response(content="Enviando mensagens...", view=None)

sent = []
errs = []
for m in guild.members:
if m.bot:
continue
try:
file = make_file()
send_kwargs = {"file": file} if file else {}
await m.send(message, **send_kwargs)
sent.append(m.id)
except Exception as e:
await interaction.user.send(f"Erro {m.id} {m.name}: {e}")
errs.append(m.id)

await interaction.user.send(f"Concluído. Enviado: {len(sent)}. Erros: {len(errs)}.")
await interaction.edit_original_response(
content=f"Concluído! Enviado para {len(sent)} membros. Erros: {len(errs)}.",
view=None,
)

@atl_spam.error
async def atl_spam_error(self, interaction: discord.Interaction, error: app_commands.AppCommandError):
if isinstance(error, app_commands.CheckFailure):
await interaction.response.send_message("Você não tem permissão para usar este comando.", ephemeral=True)


async def setup(bot):
await bot.add_cog(Admin(bot))
5 changes: 3 additions & 2 deletions bot/utils/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
from bot.utils.context import Context


async def is_pedim_or_nriver(ctx: Context):
async def is_pedim_or_nriver(ctx_or_interaction) -> bool:
pedim = 200029618277711873
nriver = 148175892596785152
return ctx.author.id == pedim or ctx.author.id == nriver
user_id = ctx_or_interaction.author.id if hasattr(ctx_or_interaction, "author") else ctx_or_interaction.user.id
return user_id == pedim or user_id == nriver


async def is_admin(ctx: Context):
Expand Down
Loading