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

feat: version 3.24 #82

Merged
merged 31 commits into from
Jun 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f081364
feat: version 3.24
Skelmis Mar 29, 2024
86afbc8
Merge branch 'master' into feat/version/3.24
Skelmis Mar 29, 2024
65e061a
chore: run updated black over the codebase
Skelmis Mar 29, 2024
e4e3982
chore: add profiling files
Skelmis Apr 1, 2024
adca53b
chore: downgrade message editing failure to debug instead of warning
Skelmis Apr 3, 2024
695dc24
chore: bump logoo to 1.4.0 to reduce log upload failures
Skelmis Apr 6, 2024
c05e395
chore: move suggestions security violations to a higher handler for m…
Skelmis Apr 10, 2024
1b0eb07
Merge branch 'master' into feat/version/3.24
Skelmis Apr 20, 2024
b74ddf7
chore: bump logoo version
Skelmis Apr 21, 2024
a6f8e15
feat: add german translations
Skelmis Apr 21, 2024
a70fa9f
fix: blocklist remove without args
Skelmis Apr 21, 2024
3ee7c72
Merge remote-tracking branch 'origin/feat/version/3.24' into feat/ver…
Skelmis Apr 21, 2024
91f4fb0
Update pt_BR.json (#83)
Davi-the-Mudkip Apr 21, 2024
7dded32
chore: move stats.py to logoo
Skelmis Apr 21, 2024
f67e6c9
Merge remote-tracking branch 'origin/feat/version/3.24' into feat/ver…
Skelmis Apr 21, 2024
5258931
feat: add SECURITY.md
Skelmis Apr 21, 2024
54cf08b
fix: missing info in ConfiguredChannelNoLongerExists error
Skelmis Apr 21, 2024
7e3c41c
chore: remove overkill data
Skelmis Apr 21, 2024
464698b
feat: add the notes command
Skelmis May 9, 2024
a6eff6e
fix: tests
Skelmis May 9, 2024
84f7e2c
feat: make thread pings configurable at the user level
Skelmis May 16, 2024
4b3b54e
feat: finish guild configs and localizing
Skelmis May 16, 2024
b262629
fix: localization
Skelmis May 16, 2024
f750e42
chore: remove a test we no longer needed
Skelmis May 16, 2024
588d68d
add todo
Skelmis May 16, 2024
dcec7c0
feat: allow resolving queued suggestions with notes
Skelmis May 18, 2024
d281c5b
fix: errors not propagating in some situations
Skelmis May 18, 2024
6cafa19
feat: log on missing base translation
Skelmis May 19, 2024
74f45cf
fix: missing base translations
Skelmis May 19, 2024
f7abdd5
pt-BR localization updates and fixes for version 3.24 (#87)
Davi-the-Mudkip May 19, 2024
d813b97
Update en_GB.json
Skelmis May 20, 2024
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
18 changes: 18 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
## Summary
<!-- What is this pull request for? -->
<!-- If this is not a version PR, remove the following -->
## Documentation changes

- XXX

## Minor changes

- XXX

## Bug fixes

- XXX

## Technical changes

- XXX

<!-- Delete to here -->

## Checklist

Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ examples/dev.py
docs/_build
test/
*.prof
profile.json
profile.html

suggestions/telemetry/error_telemetry_tracebacks
suggestions/telemetry/forbidden_errors
Expand Down
48 changes: 48 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Security Policy

## Supported Versions

The latest master branch is actively maintained and any security patches will be applied to that branch.

Older versions will not have patches back ported.

## Reporting a Vulnerability

### TLDR

We recommend opening a security advisory on GitHub, as per the [documentation](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability).

Alternatively, reach out to the maintainers via discord (`@skelmis`).

---

### Your research

We ask that anyone conducting testing:
- Makes every effort to avoid impacting other users of our systems
- Avoids any activities that disrupt, degrade or interrupt our services or may compromise other user data. This includes things such as spam, brute forcing, DoS, etc
- Keeps vulnerability information private until we have had the ability to roll out fixes


### Our commitment

If you meet the expectations laid out, we commit to:
- Acknowledge any reports and keeping you informed of how we are tracking on fixes
- Acting in good faith when interacting with you
- Recognising your contribution via means such as security advisories on the affected services and/or CVE's


We will aim to fix any issues ASAP, however as we are not a dedicated resource this may not always be possible. As such, we aim for full resolution to all acknowledged issues within a 90-day period. If this is not possible, we will enter discussions with you as to the reason for delays.


### Report details

At a minimum, your report should contain:
- The affected service
- A description of the vulnerability
- Complete reproduction steps

You may include other items to your report as you please. Some examples may be:
- The perceived impact
- The perceived likelihood of exploitation
- A list of users to credit for the disclosure
1 change: 1 addition & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ async def run_bot():
TOKEN = os.environ["PROD_TOKEN"] if bot.is_prod else os.environ["TOKEN"]

log.info("About to start SuggestionsBot | %s", bot.version)
log.info("We are in prod" if bot.is_prod else "We are launching in non-prod")
await bot.start(TOKEN)


Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@ yarl==1.7.2
zonis==2.0.0
types-aiobotocore==2.11.2
aiobotocore==2.11.2
logoo==1.3.0
logoo==1.5.0
96 changes: 33 additions & 63 deletions suggestions/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
MissingQueueLogsChannel,
MissingPermissionsToAccessQueueChannel,
InvalidFileType,
SuggestionSecurityViolation,
)
from suggestions.http_error_parser import try_parse_http_error
from suggestions.interaction_handler import InteractionHandler
Expand All @@ -55,7 +56,7 @@

class SuggestionsBot(commands.AutoShardedInteractionBot, BotBase):
def __init__(self, *args, **kwargs):
self.version: str = "Public Release 3.23"
self.version: str = "Public Release 3.24"
self.main_guild_id: int = 601219766258106399
self.legacy_beta_role_id: int = 995588041991274547
self.automated_beta_role_id: int = 998173237282361425
Expand Down Expand Up @@ -415,6 +416,26 @@ async def on_slash_command_error(
)
)

elif isinstance(exception, SuggestionSecurityViolation):
logger.critical(
"User %s looked up a suggestion from a different guild",
interaction.author.id,
extra_metadata={
"guild_id": interaction.guild_id,
"suggestion_id": exception.suggestion_id,
"author_id": interaction.author.id,
},
)
return await interaction.send(
embed=self.error_embed(
"Command failed",
exception.user_facing_message,
error_code=ErrorCode.SUGGESTION_NOT_FOUND,
error=error,
),
ephemeral=True,
)

elif isinstance(exception, commands.MissingPermissions):
perms = ",".join(i for i in exception.missing_permissions)
return await interaction.send(
Expand Down Expand Up @@ -500,7 +521,8 @@ async def on_slash_command_error(
embed=self.error_embed(
"Configuration Error",
"I cannot find your configured channel for this command.\n"
"Please ask an administrator to reconfigure one.",
"Please ask an administrator to reconfigure one.\n"
"This can be done using: `/config channel`",
error_code=ErrorCode.CONFIGURED_CHANNEL_NO_LONGER_EXISTS,
error=error,
),
Expand Down Expand Up @@ -660,7 +682,6 @@ async def load(self):
await self.stats.load()
await self.update_bot_listings()
await self.push_status()
await self.update_dev_channel()
await self.watch_for_shutdown_request()
await self.load_cogs()
await self.zonis.start()
Expand Down Expand Up @@ -724,65 +745,6 @@ async def process_watch_for_shutdown():
process_watch_for_shutdown.__task = task_1
state.add_background_task(task_1)

async def update_dev_channel(self):
if not self.is_prod:
log.info("Not watching for debug info as not on prod")
return

if not self.is_primary_cluster:
log.info("Not watching for debug info as not primary cluster")
return

state: State = self.state

async def process_watch_for_shutdown():
await self.wait_until_ready()
log.debug("Started tracking bot latency")

while not state.is_closing:
# Update once an hour
await self.sleep_with_condition(
datetime.timedelta(minutes=5).total_seconds(),
lambda: self.state.is_closing,
)

await self.garven.notify_devs(
title=f"WS latency as follows",
description=f"Timestamped for {datetime.datetime.utcnow().isoformat()}",
sender=f"N/A",
)

data = await self.garven.get_bot_ws_latency()
shard_data = data["shards"]
for i in range(0, 75, 5):
description = io.StringIO()
for o in range(0, 6):
shard = str(i + o)
try:
description.write(
f"**Shard {shard}**\nWS latency: `{shard_data[shard]['ws']}`\n"
f"Keep Alive latency: `{shard_data[shard]['keepalive']}`\n\n"
)
except KeyError:
# My lazy way of not doing env checks n math right
continue

if description.getvalue():
await self.garven.notify_devs(
title=f"WS latency",
description=description.getvalue(),
sender=f"Partial response: {data['partial_response']}",
)

await self.sleep_with_condition(
datetime.timedelta(hours=1).total_seconds(),
lambda: self.state.is_closing,
)

task_1 = asyncio.create_task(process_watch_for_shutdown())
process_watch_for_shutdown.__task = task_1
state.add_background_task(task_1)

async def update_bot_listings(self) -> None:
"""Updates the bot lists with current stats."""
if not self.is_prod:
Expand Down Expand Up @@ -869,7 +831,15 @@ def get_locale(self, key: str, locale: Locale) -> str:
return values[str(locale)]
except KeyError:
# Default to known translations if not set
return values.get("en-GB", values["en-US"])
value = values.get("en-GB")
if value is None:
value = values["en-US"]
logger.critical(
"Missing translation in en-GB file",
extra_metadata={"translation_key": key},
)

return value

@staticmethod
def inject_locale_values(
Expand Down
4 changes: 2 additions & 2 deletions suggestions/clunk2/edits.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ async def update_suggestion_message(
# We do this to avoid a race condition where the suggestion may have
# had a value modified between when it was added to the edit queue
# and the time at which it was actually edited
up_to_date_suggestion = await bot.state.suggestions_db.find(suggestion)
up_to_date_suggestion: Suggestion = await bot.state.suggestions_db.find(suggestion)
try:
await MessageEditing(
bot,
channel_id=up_to_date_suggestion.channel_id,
message_id=up_to_date_suggestion.message_id,
).edit(embed=await up_to_date_suggestion.as_embed(bot))
except (disnake.HTTPException, disnake.NotFound) as e:
logger.error(
logger.debug(
"Failed to update suggestion %s",
suggestion.suggestion_id,
extra_metadata={
Expand Down
6 changes: 6 additions & 0 deletions suggestions/cogs/blacklist_cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ async def remove(
ephemeral=True,
)

if user_id is None and suggestion_id is None:
return await interaction.send(
"Either a suggestion_id or user_id is required.",
ephemeral=True,
)

if suggestion_id:
suggestion: Suggestion = await Suggestion.from_id(
suggestion_id, interaction.guild_id, self.state
Expand Down
62 changes: 61 additions & 1 deletion suggestions/cogs/guild_config_cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ async def get(
"Using channel queue",
"Queue channel",
"Queue rejection channel",
"Ping on suggestion thread creation",
],
default=None,
),
Expand Down Expand Up @@ -244,6 +245,16 @@ async def get(
)
embed.description += log_channel

elif config == "Ping on suggestion thread creation":
locale_string = (
"CONFIG_GET_INNER_USES_THREAD_PINGS_SET"
if guild_config.ping_on_thread_creation
else "CONFIG_GET_INNER_USES_THREAD_PINGS_NOT_SET"
)
text = self.bot.get_localized_string(locale_string, interaction)

embed.description += text

elif config == "Queue channel":
log_channel = (
self.bot.get_locale(
Expand Down Expand Up @@ -536,6 +547,15 @@ async def send_full_config(self, interaction: disnake.GuildCommandInteraction):
"CONFIG_GET_INNER_AUTO_ARCHIVE_THREADS_MESSAGE", interaction.locale
).format(auto_archive_threads_text)

ping_on_thread_creation = (
"CONFIG_GET_INNER_USES_THREAD_PINGS_SET"
if guild_config.ping_on_thread_creation
else "CONFIG_GET_INNER_USES_THREAD_PINGS_NOT_SET"
)
ping_on_thread_creation = self.bot.get_localized_string(
ping_on_thread_creation, interaction
)

locale_string = (
"CONFIG_GET_INNER_SUGGESTIONS_QUEUE_SET"
if guild_config.uses_suggestion_queue
Expand All @@ -560,7 +580,7 @@ async def send_full_config(self, interaction: disnake.GuildCommandInteraction):
f"Suggestion threads: {threads}\nKeep Logs: {keep_logs}\nAnonymous suggestions: {anon}\n"
f"Automatic thread archiving: {auto_archive_threads}\nSuggestions queue: {suggestions_queue}\n"
f"Channel queue: {physical_queue}\nImages in suggestions: {images}\n"
f"Anonymous resolutions: {anonymous_resolutions}\n"
f"Anonymous resolutions: {anonymous_resolutions}\nPings in new suggestion threads: {ping_on_thread_creation}\n"
f"Queue channel: {queue_channel}\nQueue rejection channel: {queue_rejection_channel}",
color=self.bot.colors.embed_color,
timestamp=self.bot.state.now,
Expand Down Expand Up @@ -673,6 +693,46 @@ async def thread_disable(self, interaction: disnake.GuildCommandInteraction):
self.stats.type.GUILD_THREAD_DISABLE,
)

@config.sub_command_group()
async def ping_on_thread_creation(
self, interaction: disnake.GuildCommandInteraction
):
pass

@ping_on_thread_creation.sub_command(name="enable")
async def ping_on_thread_creation_enable(
self, interaction: disnake.GuildCommandInteraction
):
"""Enable pings when a thread is created on a suggestion."""
await self.modify_guild_config(
interaction,
"ping_on_thread_creation",
True,
self.bot.get_locale(
"CONFIG_PING_ON_THREAD_CREATION_ENABLE_INNER_MESSAGE",
interaction.locale,
),
"Enabled pings on new suggestion threads for guild %s",
self.stats.type.GUILD_PING_ON_THREAD_CREATE_ENABLE,
)

@ping_on_thread_creation.sub_command(name="disable")
async def ping_on_thread_creation_disable(
self, interaction: disnake.GuildCommandInteraction
):
"""Disable pings when a thread is created on a suggestion."""
await self.modify_guild_config(
interaction,
"ping_on_thread_creation",
False,
self.bot.get_locale(
"CONFIG_PING_ON_THREAD_CREATION_DISABLE_INNER_MESSAGE",
interaction.locale,
),
"Disabled pings on new suggestion threads for guild %s",
self.stats.type.GUILD_PING_ON_THREAD_CREATE_DISABLE,
)

@config.sub_command_group()
async def keeplogs(self, interaction: disnake.GuildCommandInteraction):
pass
Expand Down
Loading
Loading