Skip to content
This repository was archived by the owner on Mar 14, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
826e563
Merge pull request #1 from discord-python/master
katlyn Mar 23, 2018
03722c4
Sneks
katlyn Mar 23, 2018
8705049
Merge pull request #2 from discord-python/master
katlyn Mar 23, 2018
217839e
Added a word similarity detector.
silicWulf Mar 23, 2018
6b44d19
Add events.py to account for bad commands
katlyn Mar 23, 2018
99016fb
Silenced the screams of pain from flake8
silicWulf Mar 23, 2018
41b5c5c
Removed extra space from line 41
silicWulf Mar 23, 2018
95260a5
Added a newline
silicWulf Mar 23, 2018
300dad1
Add get_danger utility function
katlyn Mar 23, 2018
91cde5d
Add get_danger docstring
katlyn Mar 23, 2018
2055ced
Get ready for sneks
katlyn Mar 24, 2018
c3cf9a5
Line length fix
katlyn Mar 24, 2018
75f0154
Documented rattle.py
silicWulf Mar 24, 2018
1bde63d
Merge pull request #3 from discord-python/master
katlyn Mar 24, 2018
3ac3b81
Fix variable naming
katlyn Mar 24, 2018
8f74f6d
Added the get_snek core function, includes misspell detection and cor…
silicWulf Mar 24, 2018
21a0e5d
Added the snek database
silicWulf Mar 24, 2018
e927865
Fix some import errors
katlyn Mar 24, 2018
c761b7b
Added some debugging info, as well as a catch if spellcheck fails, an…
silicWulf Mar 24, 2018
40ecb63
Git screwed me... grrr
silicWulf Mar 24, 2018
2468e2b
how could I be so stupid?
silicWulf Mar 24, 2018
fa260c6
Fix embed building
katlyn Mar 24, 2018
68eaebd
Added an extra notice
silicWulf Mar 24, 2018
aecd752
I am so incredibly dense
silicWulf Mar 24, 2018
6c80c67
Reduced similarity threshold
silicWulf Mar 25, 2018
3fc366b
snek say
katlyn Mar 25, 2018
272a045
Fix flake8 not liking pickle
katlyn Mar 25, 2018
107af30
Fix whitespace
katlyn Mar 25, 2018
b3d26ee
Fixed spellcheck, removed shoddy descriptions
silicWulf Mar 25, 2018
9d2efc1
Fixed an error reeee
silicWulf Mar 25, 2018
904d416
Added some more info to the embed, fixed glaring issues
silicWulf Mar 25, 2018
5f9db70
Updated docstrings for fix_margins
silicWulf Mar 25, 2018
2837244
Fixed database probably, added some jokes
silicWulf Mar 25, 2018
8feee93
Fixed custom stuff
silicWulf Mar 25, 2018
4970c4f
Fix flake8 linting
katlyn Mar 25, 2018
3641d1b
Trying a cm fix
silicWulf Mar 25, 2018
d5fe34f
Add snek facts
katlyn Mar 25, 2018
1984019
Flake8 line too long
katlyn Mar 25, 2018
6d6f404
Added a facts command.
silicWulf Mar 25, 2018
67234de
Imported json...
silicWulf Mar 25, 2018
0b65319
Updated path I'm dumb
silicWulf Mar 25, 2018
503a4c0
Why do i keep doing this to myself
silicWulf Mar 25, 2018
721b941
Removed debug hardcode
silicWulf Mar 25, 2018
5def2bb
Renamed debug print to dprint
silicWulf Mar 25, 2018
a38d288
Added snek_pic command
silicWulf Mar 25, 2018
1f326ac
Ew fix
silicWulf Mar 25, 2018
fe8f102
n-nani?!
silicWulf Mar 25, 2018
0d78943
Fixed multi-lines
silicWulf Mar 25, 2018
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
152 changes: 152 additions & 0 deletions bot/cogs/events.py
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)
Copy link
Copy Markdown

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

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}'")
Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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")
26 changes: 26 additions & 0 deletions bot/cogs/snakes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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):
Expand All @@ -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!
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With 12 hours to go, you have no extra functionality!



Expand Down
45 changes: 45 additions & 0 deletions tools/rattle.py
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):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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
'''
Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The 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