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
84 changes: 79 additions & 5 deletions bot/cogs/amigosecreto.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@

from bot.bot_client import Bot
from bot.utils.tools import has_any_role, format_and_convert_date
from bot.utils.checks import is_authenticated
from bot.utils.checks import is_authenticated, is_pedim_or_nriver
from bot.utils.context import Context

from atlantisbot_api.models import AmigoSecretoState, AmigoSecretoPerson

from django.db.models import Q

class AmigoSecreto(commands.Cog):
def __init__(self, bot: Bot):
self.bot = bot

@commands.is_owner()
@commands.check(is_pedim_or_nriver)
@commands.command()
async def send_amigo_secreto_messages(self, ctx: Context, test: bool = True):
query = AmigoSecretoPerson.objects.all()
Expand All @@ -25,7 +25,7 @@ async def send_amigo_secreto_messages(self, ctx: Context, test: bool = True):
"Não há nenhuma mensagem de Amigo Secreto para enviar."
)

dev = self.bot.get_user(self.bot.setting.developer_id)
dev = ctx.author

if test:
await dev.send("Enviando Mensagens do Amigo Secreto em Modo de Teste")
Expand Down Expand Up @@ -97,8 +97,82 @@ async def send_amigo_secreto_messages(self, ctx: Context, test: bool = True):
)

return await ctx.send("Todas as mensagens foram enviadas.")

@staticmethod
def clear_secret_santa():
AmigoSecretoPerson.objects.all().update(receiving=False, giving_to_user=None)

def roll_secret_santa(self):
exclude: list[int] = []

person: AmigoSecretoPerson
for person in AmigoSecretoPerson.objects.filter(giving_to_user=None).all():
random_recipient = self.random_person_to(person.id, exclude)

self.bot.logger.info(person.user.ingame_name + ' is giving to ' + random_recipient.user.ingame_name)

person.giving_to_user = random_recipient.user
person.save()
exclude.append(random_recipient.id)

for person_id in exclude:
AmigoSecretoPerson.objects.filter(id=person_id).update(receiving=True)

@staticmethod
def random_person_to(pk: int, exclude: list[int]) -> AmigoSecretoPerson:
"""
Get random entry for Secret Santa, excluding people already receiving presents and the person giving himself
"""

random_person: AmigoSecretoPerson = AmigoSecretoPerson.objects.filter(
receiving=False
).filter(
Comment on lines +128 to +129

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The filter receiving=False is redundant on line 127 since it's already applied again in line 130. You can simplify this by removing the first .filter(receiving=False) and using just:

random_person: AmigoSecretoPerson = AmigoSecretoPerson.objects.filter(
    Q(receiving=False) & ~Q(id=pk) & ~Q(id__in=exclude)
).order_by('?').first()
Suggested change
receiving=False
).filter(

Copilot uses AI. Check for mistakes.
Q(receiving=False) & ~Q(id=pk) & ~Q(id__in=exclude)
).order_by('?').first()

random_person.receiving = True
random_person.save()

Comment on lines +133 to +135

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The query result could be None if no valid person is found (e.g., in edge cases or when the last person to be assigned has no valid recipient). Attempting to set random_person.receiving = True on line 133 will raise an AttributeError. You should add a null check and handle this error case appropriately:

random_person = AmigoSecretoPerson.objects.filter(...).first()
if not random_person:
    raise Exception("No valid recipient found for Secret Santa assignment")
random_person.receiving = True
random_person.save()
Suggested change
random_person.receiving = True
random_person.save()
if not random_person:
raise Exception("No valid recipient found for Secret Santa assignment")
random_person.receiving = True
random_person.save()

Copilot uses AI. Check for mistakes.
return random_person

@commands.check(is_pedim_or_nriver)
@commands.command()
async def roll_amigo_secreto(self, ctx: Context):
secret_santa_state: AmigoSecretoState = AmigoSecretoState.object()

Copilot AI Dec 8, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent method call: AmigoSecretoState.object() is called here, but elsewhere in the same file (lines 76, 177, 190) AmigoSecretoState.objects.first() is used. The method should be consistent throughout the file. Based on the pattern used in admin.py (line 512), .object() appears to be a custom method, but you should verify this is the correct method to use.

Suggested change
secret_santa_state: AmigoSecretoState = AmigoSecretoState.object()
secret_santa_state: AmigoSecretoState = AmigoSecretoState.objects.first()

Copilot uses AI. Check for mistakes.

if not secret_santa_state.end_date:
await ctx.author.send("Data de sorteio não configurada")
return

not_receiving = AmigoSecretoPerson.objects.filter(receiving=False).count()

if not_receiving == 0:
await ctx.author.send("Nenhuma pessoa sem receber presente, amigo secreto já está montado.")
return

attempts = 0
while True:
if attempts > 3:
await ctx.author.send("Muitas tentativas com erro. Contate NRiver.")
return
try:
self.roll_secret_santa()
break
except Exception as e:
self.bot.logger.error(f'Erro ao montar Amigo Secreto: {e}')
attempts += 1
await ctx.author.send('Erro ao montar Amigo Secreto, limpando e tentando novamente')
self.clear_secret_santa()

not_receiving = AmigoSecretoPerson.objects.filter(receiving=False).count()

if not_receiving > 0:
await ctx.author.send(f'Erro ao montar Amigo Secreto. Pessoas sem receber: {not_receiving}. Contate NRiver.')
return

await ctx.author.send(f'Amigo Secreto montado com sucesso. Total de pessoas: {AmigoSecretoPerson.objects.count()}')

@commands.is_owner()
@commands.check(is_pedim_or_nriver)
@commands.command()
async def check_amigo_secreto(self, ctx: Context):
state = AmigoSecretoState.objects.first()
Expand Down
6 changes: 6 additions & 0 deletions bot/utils/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
from bot.utils.context import Context


async def is_pedim_or_nriver(ctx: Context):
pedim = 200029618277711873
nriver = 148175892596785152
return ctx.author.id == pedim or ctx.author.id == nriver


async def is_admin(ctx: Context):
atlantis: discord.Guild = ctx.bot.get_guild(ctx.setting.server_id)
member: discord.Member = atlantis.get_member(ctx.author.id)
Expand Down
Loading