-
-
Notifications
You must be signed in to change notification settings - Fork 16
Team 18 #7
base: master
Are you sure you want to change the base?
Team 18 #7
Changes from 10 commits
826e563
03722c4
8705049
217839e
6b44d19
99016fb
41b5c5c
95260a5
300dad1
91cde5d
2055ced
c3cf9a5
75f0154
1bde63d
3ac3b81
8f74f6d
21a0e5d
e927865
c761b7b
40ecb63
2468e2b
fa260c6
68eaebd
aecd752
6c80c67
3fc366b
272a045
107af30
b3d26ee
9d2efc1
904d416
5f9db70
2837244
8feee93
4970c4f
3641d1b
d5fe34f
1984019
6d6f404
67234de
0b65319
503a4c0
721b941
5def2bb
a38d288
1f326ac
fe8f102
0d78943
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 |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| # coding=utf-8 | ||
| import logging | ||
|
|
||
| from discord import Embed, Member | ||
| from discord.ext.commands import ( | ||
| AutoShardedBot, BadArgument, BotMissingPermissions, | ||
| CommandError, CommandInvokeError, Context, | ||
| NoPrivateMessage, UserInputError | ||
| ) | ||
|
|
||
| from bot.constants import ( | ||
| ADMIN_ROLE, DEVLOG_CHANNEL, DEVOPS_ROLE, MODERATOR_ROLE, OWNER_ROLE, PYTHON_GUILD, SITE_API_KEY, SITE_API_USER_URL | ||
| ) | ||
|
|
||
| log = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| class Events: | ||
| """ | ||
| No commands, just event handlers | ||
| """ | ||
|
|
||
| def __init__(self, bot: AutoShardedBot): | ||
| self.bot = bot | ||
|
|
||
| async def send_updated_users(self, *users): | ||
| try: | ||
| response = await self.bot.http_session.post( | ||
| url=SITE_API_USER_URL, | ||
| json=list(users), | ||
| headers={"X-API-Key": SITE_API_KEY} | ||
| ) | ||
|
|
||
| return await response.json() | ||
| except Exception as e: | ||
| log.error(f"Failed to send role updates: {e}") | ||
| return {} | ||
|
|
||
| async def on_command_error(self, ctx: Context, e: CommandError): | ||
| command = ctx.command | ||
| parent = None | ||
|
|
||
| if command is not None: | ||
| parent = command.parent | ||
|
|
||
| if parent and command: | ||
| help_command = (self.bot.get_command("help"), parent.name, command.name) | ||
| elif command: | ||
| help_command = (self.bot.get_command("help"), command.name) | ||
| else: | ||
| help_command = (self.bot.get_command("help"),) | ||
|
|
||
| if isinstance(e, BadArgument): | ||
| await ctx.send(f"Bad argument: {e}\n") | ||
| await ctx.invoke(*help_command) | ||
| elif isinstance(e, UserInputError): | ||
| await ctx.invoke(*help_command) | ||
| elif isinstance(e, NoPrivateMessage): | ||
| await ctx.send("Sorry, this command can't be used in a private message!") | ||
| elif isinstance(e, BotMissingPermissions): | ||
| await ctx.send( | ||
| f"Sorry, it looks like I don't have the permissions I need to do that.\n\n" | ||
| f"Here's what I'm missing: **{e.missing_perms}**" | ||
| ) | ||
| elif isinstance(e, CommandInvokeError): | ||
| await ctx.send( | ||
| f"Sorry, an unexpected error occurred. Please let us know!\n\n```{e}```" | ||
| ) | ||
| raise e.original | ||
| log.error(f"COMMAND ERROR: '{e}'") | ||
|
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. This isn't logged if a non-expected CommandInvokeError happens. You could either wrap the ifs in a try - finally block, however just logging the error before you raise it would be fine. |
||
|
|
||
| async def on_ready(self): | ||
| users = [] | ||
|
|
||
| for member in self.bot.get_guild(PYTHON_GUILD).members: # type: Member | ||
| roles = [r.id for r in member.roles] # type: List[int] | ||
|
|
||
| if OWNER_ROLE in roles: | ||
| users.append({ | ||
| "user_id": member.id, | ||
| "role": OWNER_ROLE | ||
| }) | ||
| elif ADMIN_ROLE in roles: | ||
| users.append({ | ||
| "user_id": member.id, | ||
| "role": ADMIN_ROLE | ||
| }) | ||
| elif MODERATOR_ROLE in roles: | ||
| users.append({ | ||
| "user_id": member.id, | ||
| "role": MODERATOR_ROLE | ||
| }) | ||
| elif DEVOPS_ROLE in roles: | ||
| users.append({ | ||
| "user_id": member.id, | ||
| "role": DEVOPS_ROLE | ||
| }) | ||
|
|
||
| if users: | ||
| log.debug(f"{len(users)} user roles updated") | ||
| data = await self.send_updated_users(*users) # type: dict | ||
|
|
||
| if any(data.values()): | ||
| embed = Embed( | ||
| title="User roles updated" | ||
| ) | ||
|
|
||
| for key, value in data.items(): | ||
| if value: | ||
| embed.add_field( | ||
| name=key.title(), value=str(value) | ||
| ) | ||
|
|
||
| await self.bot.get_channel(DEVLOG_CHANNEL).send( | ||
| embed=embed | ||
| ) | ||
|
|
||
| async def on_member_update(self, before: Member, after: Member): | ||
| if before.roles == after.roles: | ||
| return | ||
|
|
||
| before_role_names = [role.name for role in before.roles] # type: List[str] | ||
| after_role_names = [role.name for role in after.roles] # type: List[str] | ||
| role_ids = [r.id for r in after.roles] # type: List[int] | ||
|
|
||
| log.debug(f"{before.display_name} roles changing from {before_role_names} to {after_role_names}") | ||
|
|
||
| if OWNER_ROLE in role_ids: | ||
|
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. You do this process twice, you should make a function that does this. Don't repeat yourself 😉 |
||
| self.send_updated_users({ | ||
| "user_id": after.id, | ||
| "role": OWNER_ROLE | ||
| }) | ||
| elif ADMIN_ROLE in role_ids: | ||
| self.send_updated_users({ | ||
| "user_id": after.id, | ||
| "role": ADMIN_ROLE | ||
| }) | ||
| elif MODERATOR_ROLE in role_ids: | ||
| self.send_updated_users({ | ||
| "user_id": after.id, | ||
| "role": MODERATOR_ROLE | ||
| }) | ||
| elif DEVOPS_ROLE in role_ids: | ||
| self.send_updated_users({ | ||
| "user_id": after.id, | ||
| "role": DEVOPS_ROLE | ||
| }) | ||
|
|
||
|
|
||
| def setup(bot): | ||
| bot.add_cog(Events(bot)) | ||
| log.info("Cog loaded: Events") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,6 +28,30 @@ async def get_snek(self, name: str = None) -> Dict[str, Any]: | |
| :param name: Optional, the name of the snake to get information for - omit for a random snake | ||
| :return: A dict containing information on a snake | ||
| """ | ||
| return name | ||
|
|
||
| async def get_danger(self, level: str = None) -> str: | ||
| """ | ||
| Returns the human-readable version of the danger level. | ||
| :param level: The danger level of a snek | ||
| :return: A string that is the human readable version of passed level. | ||
| """ | ||
| return { | ||
| '???': 'Danger unknown', | ||
| '---': 'Nonvenomous', | ||
| '??🐍': 'Constrictor, danger unknown', | ||
| '🐍': 'Constrictor, considered harmless', | ||
| '🐍🐍': 'Constrictor, harmful', | ||
| '🐍🐍🐍': 'Constrictor, dangerous', | ||
| '🐍🐍🐍🐍': 'Constrictor, very dangerous', | ||
| '🐍🐍🐍🐍🐍': 'Constrictor, extremely damgerous', | ||
| '??💀': 'Venomous, danger unknown', | ||
| '💀': 'Venomous, considered harmless', | ||
| '💀💀': 'Venomous, harmful', | ||
| '💀💀💀': 'Venomous, dangerous', | ||
| '💀💀💀💀': 'Venomous, very dangerous', | ||
| '💀💀💀💀💀': 'Venomous, extremely dangerous.' | ||
|
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. Could this be moved into a json file, that's already loaded? |
||
| }.get(level, 'Unknown') | ||
|
|
||
| @command() | ||
| async def get(self, ctx: Context, name: str = None): | ||
|
|
@@ -41,6 +65,8 @@ async def get(self, ctx: Context, name: str = None): | |
| :param name: Optional, the name of the snake to get information for - omit for a random snake | ||
| """ | ||
|
|
||
| print("SNEKS") | ||
|
|
||
| # Any additional commands can be placed here. Be creative, but keep it to a reasonable amount! | ||
|
Contributor
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. With 12 hours to go, you have no extra functionality! |
||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| # rattle - easy word similarity detection | ||
| def check_word(word, wordset, threshold=0.8): | ||
| def get_shortest(x, y): | ||
|
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. These helper functions should also have docstrings. |
||
| return x if len(x) < len(y) else y | ||
|
|
||
| def match_length(word, otherword): | ||
| h = len(otherword) - len(word) | ||
| word += '~' * h | ||
| return word | ||
| ''' | ||
|
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. docstring before helper functions please. |
||
| glossary: | ||
| shortest - shortest string | ||
| count - counter used to get similarity | ||
| length_diff_multiplier - multiplier for extra characters | ||
| mp_count - multiplier for the multiplier, increases on every extra space | ||
| shorter - string used as length-matched word | ||
| longer - string used as *not* `o` (is longer) | ||
| ''' | ||
| for w in wordset: | ||
| shortest = get_shortest(w, word) | ||
| count = 0 | ||
| length_diff_multiplier = 1.08 | ||
| mp_count = 1 | ||
| shorter = '' | ||
| if shortest == word: | ||
|
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. This function desperately needs block comments. runs a bit hot. |
||
| shorter = match_length(word, w) | ||
| longer = w | ||
| else: | ||
| shorter = match_length(w, word) | ||
| longer = word | ||
|
|
||
| for i, char in enumerate(longer): | ||
| if char != shorter[i]: | ||
| if char == '~': | ||
| count += mp_count * length_diff_multiplier | ||
| mp_count += 1 | ||
| else: | ||
| count += 1 | ||
|
|
||
| avg = count / len(shorter) | ||
| avg = 1.0 - avg | ||
| if avg >= threshold: | ||
| yield avg, w | ||
| else: | ||
| continue | ||
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.
Including the
(and)is unnecessary, you can accomplish the same feat with simply