Skip to content

Commit de2e5c4

Browse files
author
douglasessousa
committed
refactor: refactor for code smells too many branches and too many statements
1 parent 8ca62c7 commit de2e5c4

47 files changed

Lines changed: 125735 additions & 613 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,17 @@ TEST-**.xml
125125
# Mac OS .DS_Store, which is a file that stores custom attributes of its containing folder
126126
.DS_Store
127127
*.env*
128+
129+
# # Métricas
130+
/metrics-before-radon
131+
/metrics-before-pylint
132+
/metrics-after-pylint
133+
/metrics-before-codecarbon
134+
/metrics-before-pytest
135+
136+
extract_metrics_before_radon.py
137+
extract_metrics_before_pylint.py
138+
extract_metrics_after_pylint.py
139+
extract_score_before_pylint.py
140+
extract_metrics_before_codecarbon.py
141+
extract_metrics_before_pytest.py

bot/exts/backend/error_handler.py

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -96,24 +96,7 @@ async def on_command_error(self, ctx: Context, e: errors.CommandError) -> None:
9696
)
9797

9898
if isinstance(e, errors.CommandNotFound) and not getattr(ctx, "invoked_from_error_handler", False):
99-
# We might not invoke a command from the error handler, but it's easier and safer to ensure
100-
# this is always set rather than trying to get it exact, and shouldn't cause any issues.
101-
ctx.invoked_from_error_handler = True
102-
103-
# All errors from attempting to execute these commands should be handled by the error handler.
104-
# We wrap non CommandErrors in CommandInvokeError to mirror the behaviour of normal commands.
105-
try:
106-
if await self.try_silence(ctx):
107-
return
108-
if await self.try_run_fixed_codeblock(ctx):
109-
return
110-
await self.try_get_tag(ctx)
111-
except Exception as err:
112-
log.info("Re-handling error raised by command in error handler")
113-
if isinstance(err, errors.CommandError):
114-
await self.on_command_error(ctx, err)
115-
else:
116-
await self.on_command_error(ctx, errors.CommandInvokeError(err))
99+
await self._handle_command_not_found(ctx, e)
117100
elif isinstance(e, errors.UserInputError):
118101
log.debug(debug_message)
119102
await self.handle_user_input_error(ctx, e)
@@ -124,30 +107,55 @@ async def on_command_error(self, ctx: Context, e: errors.CommandError) -> None:
124107
log.debug(debug_message)
125108
await ctx.send(e)
126109
elif isinstance(e, errors.CommandInvokeError):
127-
if isinstance(e.original, ResponseCodeError):
128-
await self.handle_api_error(ctx, e.original)
129-
elif isinstance(e.original, LockedResourceError):
130-
await ctx.send(f"{e.original} Please wait for it to finish and try again later.")
131-
elif isinstance(e.original, InvalidInfractedUserError):
132-
await ctx.send(f"Cannot infract that user. {e.original.reason}")
133-
elif isinstance(e.original, Forbidden):
134-
try:
135-
await handle_forbidden_from_block(e.original, ctx.message)
136-
except Forbidden:
137-
await self.handle_unexpected_error(ctx, e.original)
138-
else:
139-
await self.handle_unexpected_error(ctx, e.original)
110+
await self._handle_command_invoke_error(ctx, e)
140111
elif isinstance(e, errors.ConversionError):
141-
if isinstance(e.original, ResponseCodeError):
142-
await self.handle_api_error(ctx, e.original)
143-
else:
144-
await self.handle_unexpected_error(ctx, e.original)
112+
await self._handle_conversion_error(ctx, e)
145113
elif isinstance(e, errors.DisabledCommand):
146114
log.debug(debug_message)
147115
else:
148116
# ExtensionError
149117
await self.handle_unexpected_error(ctx, e)
150118

119+
async def _handle_command_not_found(self, ctx: Context, e: errors.CommandError) -> None:
120+
"""Handle CommandNotFound errors by attempting silence, codeblock, or tag commands."""
121+
ctx.invoked_from_error_handler = True
122+
123+
try:
124+
if await self.try_silence(ctx):
125+
return
126+
if await self.try_run_fixed_codeblock(ctx):
127+
return
128+
await self.try_get_tag(ctx)
129+
except Exception as err:
130+
log.info("Re-handling error raised by command in error handler")
131+
if isinstance(err, errors.CommandError):
132+
await self.on_command_error(ctx, err)
133+
else:
134+
await self.on_command_error(ctx, errors.CommandInvokeError(err))
135+
136+
async def _handle_command_invoke_error(self, ctx: Context, e: errors.CommandInvokeError) -> None:
137+
"""Handle CommandInvokeError by dispatching on the underlying exception type."""
138+
if isinstance(e.original, ResponseCodeError):
139+
await self.handle_api_error(ctx, e.original)
140+
elif isinstance(e.original, LockedResourceError):
141+
await ctx.send(f"{e.original} Please wait for it to finish and try again later.")
142+
elif isinstance(e.original, InvalidInfractedUserError):
143+
await ctx.send(f"Cannot infract that user. {e.original.reason}")
144+
elif isinstance(e.original, Forbidden):
145+
try:
146+
await handle_forbidden_from_block(e.original, ctx.message)
147+
except Forbidden:
148+
await self.handle_unexpected_error(ctx, e.original)
149+
else:
150+
await self.handle_unexpected_error(ctx, e.original)
151+
152+
async def _handle_conversion_error(self, ctx: Context, e: errors.ConversionError) -> None:
153+
"""Handle ConversionError by dispatching on the underlying exception type."""
154+
if isinstance(e.original, ResponseCodeError):
155+
await self.handle_api_error(ctx, e.original)
156+
else:
157+
await self.handle_unexpected_error(ctx, e.original)
158+
151159
async def try_silence(self, ctx: Context) -> bool:
152160
"""
153161
Attempt to invoke the silence or unsilence command if invoke with matches a pattern.

bot/exts/filtering/_filter_lists/invite.py

Lines changed: 88 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -59,29 +59,59 @@ async def actions_for(
5959
) -> tuple[ActionSettings | None, list[str], dict[ListType, list[Filter]]]:
6060
"""Dispatch the given event to the list's filters, and return actions to take and messages to relay to mods."""
6161
text = clean_input(ctx.content, keep_newlines=True)
62-
63-
matches = list(DISCORD_INVITE.finditer(text))
64-
invite_codes = {m.group("invite") for m in matches}
62+
matches, invite_codes, refined_invites = self._process_invite_codes(text)
6563
if not invite_codes:
6664
return None, [], {}
67-
all_triggers = {}
6865

66+
_, failed = self[ListType.ALLOW].defaults.validations.evaluate(ctx)
67+
check_if_allowed = not failed
68+
69+
invites_for_inspection, unknown_invites = await self._fetch_and_categorize_invites(
70+
refined_invites, check_if_allowed
71+
)
72+
73+
new_ctx = ctx.replace(content={invite.guild.id for invite in invites_for_inspection.values()})
74+
triggered = await self[ListType.DENY].filter_list_result(new_ctx)
75+
76+
blocked_invites, invites_for_inspection = self._apply_deny_filters(invites_for_inspection, triggered)
77+
78+
all_triggers = await self._check_allow_list(
79+
ctx, invites_for_inspection, unknown_invites, check_if_allowed
80+
)
81+
82+
if not triggered and not unknown_invites:
83+
return None, [], all_triggers
84+
85+
actions = self._determine_actions(unknown_invites, triggered, all_triggers)
86+
87+
blocked_invites |= unknown_invites
88+
ctx.matches += {match[0] for match in matches if refined_invites.get(match.group("invite")) in blocked_invites}
89+
ctx.alert_embeds += (self._guild_embed(invite) for invite in blocked_invites.values() if invite)
90+
if unknown_invites:
91+
ctx.potential_phish[self] = set(unknown_invites)
92+
93+
messages = self._build_messages(triggered, unknown_invites)
94+
return actions, messages, all_triggers
95+
96+
@staticmethod
97+
def _process_invite_codes(text: str) -> tuple[list[re.Match], set[str], dict[str, str]]:
98+
"""Extract invite codes from the text and refine obfuscated codes."""
99+
matches = list(DISCORD_INVITE.finditer(text))
100+
invite_codes = {m.group("invite") for m in matches}
69101
refined_invites = {}
70102
for invite_code in invite_codes:
71-
# Attempt to overcome an obfuscated invite.
72-
# If the result is incorrect, it won't make the whitelist more permissive or the blacklist stricter.
73103
refined_invite_code = invite_code
74104
if match := REFINED_INVITE_CODE.search(invite_code):
75105
refined_invite_code = match.group("invite")
76106
refined_invites[invite_code] = refined_invite_code
77-
78-
_, failed = self[ListType.ALLOW].defaults.validations.evaluate(ctx)
79-
# If the allowed list doesn't operate in the context, unknown invites are allowed.
80-
check_if_allowed = not failed
81-
82-
# Sort the invites into two categories:
83-
invites_for_inspection = dict() # Found guild invites requiring further inspection.
84-
unknown_invites = dict() # Either don't resolve or group DMs.
107+
return matches, invite_codes, refined_invites
108+
109+
async def _fetch_and_categorize_invites(
110+
self, refined_invites: dict[str, str], check_if_allowed: bool
111+
) -> tuple[dict[str, Invite], dict[str, Invite | None]]:
112+
"""Fetch invites from the Discord API and categorize them into guild invites or unknown/group DMs."""
113+
invites_for_inspection = {}
114+
unknown_invites = {}
85115
for invite_code in refined_invites.values():
86116
try:
87117
invite = await bot.instance.fetch_invite(invite_code)
@@ -91,63 +121,72 @@ async def actions_for(
91121
else:
92122
if invite.guild:
93123
invites_for_inspection[invite_code] = invite
94-
elif check_if_allowed: # Group DM
124+
elif check_if_allowed:
95125
unknown_invites[invite_code] = invite
126+
return invites_for_inspection, unknown_invites
127+
128+
async def _check_allow_list(
129+
self, ctx: FilterContext, invites_for_inspection: dict[str, Invite],
130+
unknown_invites: dict[str, Invite | None], check_if_allowed: bool
131+
) -> dict[ListType, list[Filter]]:
132+
"""Check remaining invites against the allow list and update unknown invites."""
133+
if not check_if_allowed:
134+
return {}
135+
guilds_for_inspection = {invite.guild.id for invite in invites_for_inspection.values()}
136+
new_ctx = ctx.replace(content=guilds_for_inspection)
137+
all_triggers = {
138+
ListType.ALLOW: [
139+
filter_ for filter_ in self[ListType.ALLOW].filters.values()
140+
if await filter_.triggered_on(new_ctx)
141+
]
142+
}
143+
allowed = {filter_.content for filter_ in all_triggers[ListType.ALLOW]}
144+
unknown_invites.update({
145+
code: invite for code, invite in invites_for_inspection.items() if invite.guild.id not in allowed
146+
})
147+
return all_triggers
96148

97-
# Find any blocked invites
98-
new_ctx = ctx.replace(content={invite.guild.id for invite in invites_for_inspection.values()})
99-
triggered = await self[ListType.DENY].filter_list_result(new_ctx)
149+
@staticmethod
150+
def _apply_deny_filters(
151+
invites_for_inspection: dict[str, Invite], triggered: list[Filter]
152+
) -> tuple[dict[str, Invite], dict[str, Invite]]:
153+
"""Separate blocked invites and filter out partnered/verified guilds from inspection."""
100154
blocked_guilds = {filter_.content for filter_ in triggered}
101155
blocked_invites = {
102-
code: invite for code, invite in invites_for_inspection.items() if invite.guild.id in blocked_guilds
156+
code: invite for code, invite in invites_for_inspection.items()
157+
if invite.guild.id in blocked_guilds
103158
}
104-
105-
# Remove the ones which are already confirmed as blocked, or otherwise ones which are partnered or verified.
106-
invites_for_inspection = {
159+
filtered_invites = {
107160
code: invite for code, invite in invites_for_inspection.items()
108161
if invite.guild.id not in blocked_guilds
109-
and "PARTNERED" not in invite.guild.features and "VERIFIED" not in invite.guild.features
162+
and "PARTNERED" not in invite.guild.features
163+
and "VERIFIED" not in invite.guild.features
110164
}
165+
return blocked_invites, filtered_invites
111166

112-
# Remove any remaining invites which are allowed
113-
guilds_for_inspection = {invite.guild.id for invite in invites_for_inspection.values()}
114-
115-
if check_if_allowed: # Whether unknown invites need to be checked.
116-
new_ctx = ctx.replace(content=guilds_for_inspection)
117-
all_triggers[ListType.ALLOW] = [
118-
filter_ for filter_ in self[ListType.ALLOW].filters.values()
119-
if await filter_.triggered_on(new_ctx)
120-
]
121-
allowed = {filter_.content for filter_ in all_triggers[ListType.ALLOW]}
122-
unknown_invites.update({
123-
code: invite for code, invite in invites_for_inspection.items() if invite.guild.id not in allowed
124-
})
125-
126-
if not triggered and not unknown_invites:
127-
return None, [], all_triggers
128-
167+
def _determine_actions(
168+
self, unknown_invites: dict, triggered: list[Filter],
169+
all_triggers: dict[ListType, list[Filter]]
170+
) -> ActionSettings | None:
171+
"""Determine the actions to take based on triggered filters and unknown invites."""
129172
actions = None
130-
if unknown_invites: # There are invites which weren't allowed but aren't explicitly blocked.
173+
if unknown_invites:
131174
actions = self[ListType.ALLOW].defaults.actions
132-
# Blocked invites come second so that their actions have preference.
133175
if triggered:
134176
if actions:
135177
actions = actions.union(self[ListType.DENY].merge_actions(triggered))
136178
else:
137179
actions = self[ListType.DENY].merge_actions(triggered)
138180
all_triggers[ListType.DENY] = triggered
181+
return actions
139182

140-
blocked_invites |= unknown_invites
141-
ctx.matches += {match[0] for match in matches if refined_invites.get(match.group("invite")) in blocked_invites}
142-
ctx.alert_embeds += (self._guild_embed(invite) for invite in blocked_invites.values() if invite)
143-
if unknown_invites:
144-
ctx.potential_phish[self] = set(unknown_invites)
145-
183+
def _build_messages(self, triggered: list[Filter], unknown_invites: dict) -> list[str]:
184+
"""Build alert messages for triggered filters and unknown invites."""
146185
messages = self[ListType.DENY].format_messages(triggered)
147186
messages += [
148187
f"`{code} - {invite.guild.id}`" if invite else f"`{code}`" for code, invite in unknown_invites.items()
149188
]
150-
return actions, messages, all_triggers
189+
return messages
151190

152191
@staticmethod
153192
def _guild_embed(invite: Invite) -> Embed:

0 commit comments

Comments
 (0)