-
Notifications
You must be signed in to change notification settings - Fork 26
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
Add flagging functionality for moderation #556
base: main
Are you sure you want to change the base?
Changes from all commits
13d74fb
82d3a0c
1742ab6
599452e
efd1174
53a6588
5db51cb
58fa186
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -169,4 +169,6 @@ enum CaseType { | |
UNJAIL | ||
SNIPPETUNBAN | ||
UNTEMPBAN | ||
FLAG | ||
UNFLAG | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import discord | ||
from discord.ext import commands | ||
|
||
from prisma.enums import CaseType | ||
from tux.bot import Tux | ||
from tux.database.controllers.case import CaseController | ||
from tux.utils import checks | ||
from tux.utils.flags import FlagFlags, generate_usage | ||
|
||
from . import ModerationCogBase | ||
|
||
|
||
class Unflag(ModerationCogBase): | ||
def __init__(self, bot: Tux) -> None: | ||
super().__init__(bot) | ||
self.case_controller = CaseController() | ||
self.flag.usage = generate_usage(self.flag, FlagFlags) | ||
|
||
@commands.hybrid_command( | ||
name="flag", | ||
aliases=["fl"], | ||
) | ||
@commands.guild_only() | ||
@checks.has_pl(2) | ||
async def flag( | ||
self, | ||
ctx: commands.Context[Tux], | ||
member: discord.Member, | ||
*, | ||
flags: FlagFlags, | ||
) -> None: | ||
""" | ||
Flag a member from the server. | ||
|
||
Parameters | ||
---------- | ||
ctx : commands.Context[Tux] | ||
The context in which the command is being invoked. | ||
member : discord.Member | ||
The member to flag. | ||
flags : FlagFlags | ||
The flags for the command. (reason: str, silent: bool) | ||
""" | ||
|
||
assert ctx.guild | ||
|
||
if await self.is_flagged(ctx.guild.id, member.id): | ||
await ctx.send("User is already flagged.", delete_after=30, ephemeral=True) | ||
return | ||
|
||
moderator = ctx.author | ||
|
||
if not await self.check_conditions(ctx, member, moderator, "flag"): | ||
return | ||
|
||
case = await self.db.case.insert_case( | ||
case_user_id=member.id, | ||
case_moderator_id=ctx.author.id, | ||
case_type=CaseType.FLAG, | ||
case_reason=flags.reason, | ||
guild_id=ctx.guild.id, | ||
) | ||
|
||
await self.handle_case_response( | ||
ctx, | ||
CaseType.FLAG, | ||
case.case_number, | ||
flags.reason, | ||
member, | ||
dm_sent=False, | ||
silent_action=True, | ||
) | ||
|
||
async def is_flagged(self, guild_id: int, user_id: int) -> bool: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Consider moving is_flagged method to a common location The is_flagged method is duplicated in both flag.py and unflag.py. Consider moving this to a common location, such as a base class or utility module, to avoid code repetition and improve maintainability.
|
||
""" | ||
Check if a user is flagged. | ||
|
||
Parameters | ||
---------- | ||
guild_id : int | ||
The ID of the guild to check in. | ||
user_id : int | ||
The ID of the user to check. | ||
|
||
Returns | ||
------- | ||
bool | ||
True if the user is flagged, False otherwise. | ||
""" | ||
|
||
flag_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.FLAG) | ||
unflag_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.UNFLAG) | ||
|
||
flag_count = sum(case.case_user_id == user_id for case in flag_cases) | ||
unflag_count = sum(case.case_user_id == user_id for case in unflag_cases) | ||
|
||
return flag_count > unflag_count | ||
|
||
|
||
async def setup(bot: Tux) -> None: | ||
await bot.add_cog(Unflag(bot)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -86,6 +86,7 @@ async def timeout( | |
flags.reason, | ||
member, | ||
dm_sent, | ||
False, | ||
flags.duration, | ||
) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import discord | ||
from discord.ext import commands | ||
|
||
from prisma.enums import CaseType | ||
from tux.bot import Tux | ||
from tux.database.controllers.case import CaseController | ||
from tux.utils import checks | ||
from tux.utils.flags import UnFlagFlags, generate_usage | ||
|
||
from . import ModerationCogBase | ||
|
||
|
||
class Flag(ModerationCogBase): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (complexity): Consider consolidating flag-related functionality into a single cog and moving shared methods to a utility module. The current implementation introduces unnecessary complexity through code duplication and separation of closely related functionality. Consider the following improvements:
class FlagManagement(ModerationCogBase):
def __init__(self, bot: Tux) -> None:
super().__init__(bot)
self.case_controller = CaseController()
self.flag.usage = generate_usage(self.flag, FlagFlags)
self.unflag.usage = generate_usage(self.unflag, UnFlagFlags)
@commands.hybrid_command(name="flag", aliases=["fl"])
async def flag(self, ctx: commands.Context[Tux], member: discord.Member, *, flags: FlagFlags) -> None:
# Implement flag logic here
@commands.hybrid_command(name="unflag", aliases=["ufl"])
async def unflag(self, ctx: commands.Context[Tux], member: discord.Member, *, flags: UnFlagFlags) -> None:
# Implement unflag logic here (current implementation)
# Other methods...
# In tux/utils/moderation.py
async def is_flagged(case_controller: CaseController, guild_id: int, user_id: int) -> bool:
flag_cases = await case_controller.get_all_cases_by_type(guild_id, CaseType.FLAG)
unflag_cases = await case_controller.get_all_cases_by_type(guild_id, CaseType.UNFLAG)
flag_count = sum(case.case_user_id == user_id for case in flag_cases)
unflag_count = sum(case.case_user_id == user_id for case in unflag_cases)
return flag_count > unflag_count
# In FlagManagement cog
from tux.utils.moderation import is_flagged
class FlagManagement(ModerationCogBase):
# ...
async def unflag(self, ctx: commands.Context[Tux], member: discord.Member, *, flags: UnFlagFlags) -> None:
# ...
if not await is_flagged(self.case_controller, ctx.guild.id, member.id):
await ctx.send("User is not flagged.", delete_after=30, ephemeral=True)
return
# ...
# Remove the is_flagged method from this class These changes will reduce code duplication, improve maintainability, and provide a more logical structure for flag-related operations while maintaining all existing functionality. |
||
def __init__(self, bot: Tux) -> None: | ||
super().__init__(bot) | ||
self.case_controller = CaseController() | ||
self.unflag.usage = generate_usage(self.unflag, UnFlagFlags) | ||
|
||
@commands.hybrid_command( | ||
name="unflag", | ||
aliases=["ufl"], | ||
) | ||
@commands.guild_only() | ||
@checks.has_pl(2) | ||
async def unflag( | ||
self, | ||
ctx: commands.Context[Tux], | ||
member: discord.Member, | ||
*, | ||
flags: UnFlagFlags, | ||
) -> None: | ||
""" | ||
Unflag a member from the server. | ||
|
||
Parameters | ||
---------- | ||
ctx : commands.Context[Tux] | ||
The context in which the command is being invoked. | ||
member : discord.Member | ||
The member to unflag. | ||
flags : UnFlagFlags | ||
The flags for the command. (reason: str, silent: bool) | ||
""" | ||
|
||
assert ctx.guild | ||
|
||
if not await self.is_flagged(ctx.guild.id, member.id): | ||
await ctx.send("User is not flagged.", delete_after=30, ephemeral=True) | ||
return | ||
|
||
moderator = ctx.author | ||
|
||
if not await self.check_conditions(ctx, member, moderator, "unflag"): | ||
return | ||
|
||
case = await self.db.case.insert_case( | ||
case_user_id=member.id, | ||
case_moderator_id=ctx.author.id, | ||
case_type=CaseType.UNFLAG, | ||
case_reason=flags.reason, | ||
guild_id=ctx.guild.id, | ||
) | ||
|
||
await self.handle_case_response( | ||
ctx, | ||
CaseType.UNFLAG, | ||
case.case_number, | ||
flags.reason, | ||
member, | ||
dm_sent=False, | ||
silent_action=True, | ||
) | ||
|
||
async def is_flagged(self, guild_id: int, user_id: int) -> bool: | ||
""" | ||
Check if a user is flagged. | ||
|
||
Parameters | ||
---------- | ||
guild_id : int | ||
The ID of the guild to check in. | ||
user_id : int | ||
The ID of the user to check. | ||
|
||
Returns | ||
------- | ||
bool | ||
True if the user is flagged, False otherwise. | ||
""" | ||
|
||
flag_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.FLAG) | ||
unflag_cases = await self.case_controller.get_all_cases_by_type(guild_id, CaseType.UNFLAG) | ||
|
||
flag_count = sum(case.case_user_id == user_id for case in flag_cases) | ||
unflag_count = sum(case.case_user_id == user_id for case in unflag_cases) | ||
|
||
return flag_count > unflag_count | ||
|
||
|
||
async def setup(bot: Tux) -> None: | ||
await bot.add_cog(Flag(bot)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): Consider consolidating flag-related functionality into a single cog and moving shared methods to a utility module.
The current implementation introduces unnecessary complexity through code duplication and inconsistent naming. To simplify and improve maintainability:
is_flagged
method to a shared utility module:Then, in the FlagManagement cog:
These changes will reduce code duplication, improve maintainability, and resolve the naming inconsistency while keeping all functionality intact.