Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork731
refactor: update botstrap to be more beginner-friendly#3417
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
refactor: update botstrap to be more beginner-friendly#3417
Uh oh!
There was an error while loading.Please reload this page.
Conversation
496b553 toa0b56a6CompareThere 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.
Few review comments.
Can we also squash down the history a little bit? I don't think we need 21 commits for the changes here. Obviously keep the constants one separate but I think we can squash down a lot of the other ones.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
f5f2c3c toa61eb26Compare@jb3 I've compressed the history and addressed your comments in the updated history. Comments should now follow pep8, formatted with ruff, and silenced pyright. |
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.
Thanks for addressing review feedback.
Only a couple of points left now, but also a couple of wider points:
- I think the
withblock we use now to run the script is too long and I think things like the webhook management & emoji management should be moved into their own methods that we then call (the with should be as small as possible really). - The existing webhook if statement is still a bit scary (I thought I'd left a review comment but can't see/find it now!), I'd prefer creating a new method along the lines of
find_matching_webhook, something like:
deffind_matching_webhook(existing_webhooks,webhook_model,formatted_name,channel_id):forhookinexisting_webhooks:ifhook["id"]==str(webhook_model.id):returnhook["id"]ifhook["name"]==formatted_nameandhook["channel_id"]==str(channel_id):returnhook["id"]returnNone
It's all just become a little bit too complex to follow under that context manager and I think that some splitting up into smaller more digestible methods is a good idea here.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
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.
Sorry for these comments all being in parts, just keep doing scans and picking up new bits.
Can we also standardise on whether you're using f-strings in this file or using%s interpolation? There is a mix currently (I appreciate it was f-strings before which is not correct, but if you're adding some f-strings and some %s strings we may as well unify).
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
- provide completion message- silence httpcore logger- filter out botcore's warning for patching send_typing- use short url for contributing link- only use logging.warning and up for things that need user action- use logging.fatal when exiting due to error- use % for all logging statements
a61eb26 to57c92b0Comparethis lowers the amount of requests we make and reduces the chance of ratelimiting
* request all webhooks in a single call rather than per configured webhook* Enable support for multiple identical test botssharing the same webhookThis should prevent the limit of 10 webhooks per channel from being reachedwithout needing to share a specific guild configuration for the PyDisstaff test guild
this makes it easier to configure webhooks:we now only need to set their ID and not their channel.Setting the channel ID is only use for botstrap configuration, anyhow.
57c92b0 to82fa0b1CompareUh oh!
There was an error while loading.Please reload this page.
botstrap.py Outdated
| if ( | ||
| # check the existing ID matches the configured one | ||
| existing_hook["id"]==str(webhook_model.id) | ||
| or ( | ||
| # check if the name and the channel ID match the configured ones | ||
| existing_hook["name"]==formatted_webhook_name | ||
| andexisting_hook["channel_id"]==str(all_channels[webhook_name]) | ||
| ) | ||
| ): | ||
| webhook_id=existing_hook["id"] | ||
| break |
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.
I have commented every review this needs changing 🥲.
Split out to a helper method without the complex conditions. Also, comments should always have a capital (and only be present if they actually add something, for simple conditionals they generally don't).
deffind_matching_webhook(existing_webhooks,webhook_model,formatted_name,channel_id):forhookinexisting_webhooks:ifhook["id"]==str(webhook_model.id):returnhook["id"]ifhook["name"]==formatted_nameandhook["channel_id"]==str(channel_id):returnhook["id"]returnNone
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.
I sort of cleaned up this code but I'm not sure about the separate method with just how many specific inputs are required.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
botstrap.py Outdated
| withbotstrap: | ||
| botstrap.run() |
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.
I'm not sure if this is the way this should be done or whether it'd be cleaner to create a DiscordClient here, pass it into the botstrap initialiser and then avoid having to define the__exit__ method for the BotStrapper class.
e.g.
withDiscordClient(guild_id=GUILD_ID)asdiscord_client:botstrap=BotStrapper(client=discord_client)
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.
I would prefer to manage the DiscordClient internally on the botstrap class, even if we use contextlib to manage the context manager.
DiscordClient should not be used by anything other than the BotStrap class, and an instance of it outside of botstrap doesn't need to exist.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
botstrap.py Outdated
| defcreate_forum_channel(self,channel_name_:str,category_id_:int|str|None=None)->str: | ||
| """Creates a new forum channel.""" | ||
| payload= {"name":channel_name_,"type":GUILD_FORUM_TYPE} | ||
| payload:dict[str,Any]= {"name":channel_name_,"type":GUILD_FORUM_TYPE} |
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.
nitpick:dict[str, object] (avoid Any unless really necessary)
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.
Any not necessary for these. +1
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.
| log.info("Botstrap completed successfully. Updated configuration has been written to %s",ENV_FILE) | ||
| else: | ||
| log.info("Botstrap completed successfully. No changes were necessary.") | ||
| sys.exit(changes_made) |
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.
Why exit with an error if we make changes? Makes sense for a linter, not for this.
| withbotstrap: | ||
| changes_made=botstrap.run() | ||
| ifchanges_made: | ||
| log.info("Botstrap completed successfully. Updated configuration has been written to %s",ENV_FILE) | ||
| else: | ||
| log.info("Botstrap completed successfully. No changes were necessary.") |
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.
Space.
| withbotstrap: | |
| changes_made=botstrap.run() | |
| ifchanges_made: | |
| log.info("Botstrap completed successfully. Updated configuration has been written to %s",ENV_FILE) | |
| else: | |
| log.info("Botstrap completed successfully. No changes were necessary.") | |
| withbotstrap: | |
| changes_made=botstrap.run() | |
| ifchanges_made: | |
| log.info("Botstrap completed successfully. Updated configuration has been written to %s",ENV_FILE) | |
| else: | |
| log.info("Botstrap completed successfully. No changes were necessary.") | |
| defget_emoji_contents(self,id_:str|int)->bytes|None: | ||
| """Fetches the image data for an emoji by ID.""" | ||
| # Emojis are located at https://cdn.discordapp.com/emojis/{emoji_id}.{ext} | ||
| response=self.get(f"{self.CDN_BASE_URL}/emojis/{id_!s}.webp") |
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.
Shouldn't fetch webp if you then submitimage/png, even if Discord is accepting it this doesn't seem right.
| """ | ||
| # Fetch first to modify, not overwrite | ||
| current_flags=self.get_app_info().get("flags",0) | ||
| new_flags=current_flags|1<<15|1<<19 |
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.
No magic values here.
Uh oh!
There was an error while loading.Please reload this page.
Update botstrap to be much more userfriendly. This silences noisy logs that we don't want to see or care about when downloading new server.
We also provide a success message when the entire system is successful.
I've also implemented some small caching in the botcore client to only make requests when necessary, and to only make one request to get all of the webhooks. While yes, webhooks are free, I left request logging enabled so the user could see what requests were made. I didn't see a good reason to silence those, both for transparency and because they already provide logging.
We also provide an invite link if the bot isn't in the guild already, but it is configured.
I've also added support which sets the app's flags to enable message content intents and member intent if they aren't already enabled.
closes#3414