Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Models] Add soft delete field #388

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions ballsdex/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ class BallInstance(models.Model):
default=None,
)
extra_data = fields.JSONField(default={})
deleted = fields.BooleanField(default=False)

class Meta:
unique_together = ("player", "id")
Expand Down
24 changes: 19 additions & 5 deletions ballsdex/packages/admin/cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -1039,7 +1039,11 @@ async def balls_transfer(
@balls.command(name="reset")
@app_commands.checks.has_any_role(*settings.root_role_ids)
async def balls_reset(
self, interaction: discord.Interaction, user: discord.User, percentage: int | None = None
self,
interaction: discord.Interaction,
user: discord.User,
percentage: int | None = None,
hard: bool = False,
):
"""
Reset a player's countryballs.
Expand All @@ -1050,6 +1054,8 @@ async def balls_reset(
The user you want to reset the countryballs of.
percentage: int | None
The percentage of countryballs to delete, if not all. Used for sanctions.
hard: bool
If true, the countryballs are deleted permanently. Otherwise, they are soft deleted.
"""
player = await Player.get_or_none(discord_id=user.id)
if not player:
Expand Down Expand Up @@ -1088,16 +1094,24 @@ async def balls_reset(
balls = await BallInstance.filter(player=player)
to_delete = random.sample(balls, int(len(balls) * (percentage / 100)))
for ball in to_delete:
await ball.delete()
if hard:
await ball.delete()
else:
ball.deleted = True
await ball.save()
count = len(to_delete)
else:
count = await BallInstance.filter(player=player).delete()
if hard:
count = await BallInstance.filter(player=player).delete()
else:
count = await BallInstance.filter(player=player).update(deleted=True)
await interaction.followup.send(
f"{count} {settings.plural_collectible_name} from {user} have been deleted.",
f"{count} {settings.plural_collectible_name} from {user} have been "
f"{'soft ' if not hard else ''}deleted.",
ephemeral=True,
)
await log_action(
f"{interaction.user} deleted {percentage or 100}% of "
f"{interaction.user} {'soft ' if not hard else ''}deleted {percentage or 100}% of "
f"{player}'s {settings.plural_collectible_name}.",
self.bot,
)
Expand Down
14 changes: 10 additions & 4 deletions ballsdex/packages/balls/cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,11 @@ async def list(
return

await player.fetch_related("balls")
filters = {"ball__id": countryball.pk} if countryball else {}
filters = (
{"ball__id": countryball.pk, "deleted": False} if countryball else {"deleted": False}
)
if special:
filters["special"] = special
filters["special"] = special # type: ignore
if sort:
if sort == SortingChoices.duplicates:
countryballs = await player.balls.filter(**filters)
Expand Down Expand Up @@ -291,7 +293,7 @@ async def completion(
bot_countryballs = {x: y.emoji_id for x, y in balls.items() if y.enabled}

# Set of ball IDs owned by the player
filters = {"player__discord_id": user_obj.id, "ball__enabled": True}
filters = {"player__discord_id": user_obj.id, "ball__enabled": True, "deleted": False}
if special:
filters["special"] = special
bot_countryballs = {
Expand Down Expand Up @@ -497,7 +499,10 @@ async def favorite(
if settings.max_favorites == 1
else f"{settings.plural_collectible_name}"
)
if await player.balls.filter(favorite=True).count() >= settings.max_favorites:
if (
await player.balls.filter(favorite=True, deleted=False).count()
>= settings.max_favorites
):
await interaction.response.send_message(
f"You cannot set more than {settings.max_favorites} favorite {grammar}.",
ephemeral=True,
Expand Down Expand Up @@ -676,6 +681,7 @@ async def count(
return
assert interaction.guild
filters = {}
filters["deleted"] = False
if countryball:
filters["ball"] = countryball
if shiny is not None:
Expand Down
4 changes: 3 additions & 1 deletion ballsdex/packages/countryballs/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ async def catch_ball(
# None is added representing the common countryball
special = random.choices(population=population + [None], weights=weights, k=1)[0]

is_new = not await BallInstance.filter(player=player, ball=self.ball.model).exists()
is_new = not await BallInstance.filter(
player=player, ball=self.ball.model, deleted=True
).exists()
ball = await BallInstance.create(
ball=self.ball.model,
player=player,
Expand Down
10 changes: 7 additions & 3 deletions ballsdex/packages/players/cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,12 @@ async def delete(self, interaction: discord.Interaction):
await view.wait()
if view.value is None or not view.value:
return
player, _ = await PlayerModel.get_or_create(discord_id=interaction.user.id)
await player.delete()
await interaction.response.defer(ephemeral=True, thinking=True)
balls = await BallInstance.filter(player__discord_id=interaction.user.id)
for ball in balls:
ball.deleted = True
await ball.save()
await interaction.followup.send("Your player data has been deleted.", ephemeral=True)

@friend.command(name="add")
async def friend_add(self, interaction: discord.Interaction, user: discord.User):
Expand Down Expand Up @@ -631,7 +635,7 @@ async def get_items_csv(player: PlayerModel) -> BytesIO:
"""
Get a CSV file with all items of the player.
"""
balls = await BallInstance.filter(player=player).prefetch_related(
balls = await BallInstance.filter(player=player, deleted=True).prefetch_related(
"ball", "trade_player", "special"
)
txt = (
Expand Down
1 change: 1 addition & 0 deletions ballsdex/packages/trade/cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ async def bulk_add(
)
return
filters = {}
filters["deleted"] = False
if countryball:
filters["ball"] = countryball
if shiny:
Expand Down
4 changes: 4 additions & 0 deletions migrations/models/33_20240906161013_update.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- upgrade --
ALTER TABLE "ballinstance" ADD "deleted" BOOL NOT NULL DEFAULT False;
-- downgrade --
ALTER TABLE "ballinstance" DROP COLUMN "deleted";
4 changes: 4 additions & 0 deletions migrations/models/36_20241125161013_update.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- upgrade --
ALTER TABLE "ballinstance" ADD "deleted" BOOL NOT NULL DEFAULT False;
-- downgrade --
ALTER TABLE "ballinstance" DROP COLUMN "deleted";
Loading