Skip to content
This repository was archived by the owner on Mar 14, 2021. It is now read-only.
3 changes: 3 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ name = "pypi"

[packages]
"72eb2aa" = {file = "https://github.com/Rapptz/discord.py/archive/rewrite.zip"}
aiohttp = "*"
aiodns = "*"
bs4 = "*"
html2text = "*"
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.

You have edited the Pipfile directly, and in a way that will break discord.py. Please revert your Pipfile and read over the doc/ folder again.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I don't believe we'd had this change to the Pipfile PR'd yet, because I don't remember deleting the aiohttp/websockets lines. But also -- doesn't discord.py itself pin these two deps in its own requirements.txt?

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.

It does pin aiohttp and websockets, but Pipenv doesn't pick up on it correctly if they aren't specified directly in the pipfile. You also can't just use the latest version of aiohttp, it's not compatible.

I make a PR this morning, maybe check that out.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Gotcha, & just saw that! I'll fix all this as soon as I get home.


[dev-packages]
"flake8" = "*"
Expand Down
55 changes: 47 additions & 8 deletions bot/cogs/snakes.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
# coding=utf-8
import logging
from typing import Any, Dict
import re

from discord.ext.commands import AutoShardedBot, Context, command
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.

Why not keep it like this? Seems cleaner than what you did below

import aiohttp
import bs4
import discord
import html2text
from discord.ext import commands

log = logging.getLogger(__name__)
API = 'http://en.wikipedia.org/w/api.php?format=json&redirects=1&action='

rSENTENCE = re.compile(r'^.+?\.')
rBRACK = re.compile(r'[[(].+?[\])]')


class Snakes:
"""
Snake-related commands
"""

def __init__(self, bot: AutoShardedBot):
def __init__(self, bot):
self.bot = bot
self.aexec = bot.loop.run_in_executor
self.session = aiohttp.ClientSession(loop=bot.loop)
self.h2md = html2text.HTML2Text() # TODO: use
self.base_query = API + 'parse&prop=text&page={}'
self.secs_query = API + 'parse&prop=sections&page={}'
self.img_query = API + 'query&titles={}&prop=pageimages&pithumbsize=300'

async def get_snek(self, name: str = None) -> Dict[str, Any]:
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.

Why did you remove the type hinting?

Copy link
Copy Markdown
Author

@supposedly supposedly Mar 23, 2018

Choose a reason for hiding this comment

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

Sorry. My partner was for a short while only able to use python 3.5 (and typing was added in 3.6) so I started removing hints preemptively for compatibility -- didn't take care to put them all back once he was able to get on 3.6, though.

async def get_snek(self, name=None):
"""
Go online and fetch information about a snake

Expand All @@ -28,9 +42,32 @@ 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
"""
# TODO: Random will be done by fetching from Special:RandomInCategory/Venomous_snakes, or something
async with self.session.get(self.base_query.format(name)) as pg_resp, \
self.session.get(self.secs_query.format(name)) as sc_resp, \
self.session.get(self.img_query.format(name)) as img_resp:
data = await pg_resp.json()
secs = await sc_resp.json()
img = await img_resp.json()
tidbits = []
soup = bs4.BeautifulSoup(data['parse']['text']['*'])
for section in secs['parse']['sections']:
for tag in await self.aexec(None, soup.find(id=section['anchor']).find_all_next): # FIXME: inefficient...?
if tag.name == 'p':
try:
tidbits.append(rBRACK.sub('', rSENTENCE.match(tag.text)[0]))
except TypeError:
pass
break
try:
pgid = str(data['parse']['pageid'])
imglink = img['query']['pages'][pgid]['thumbnail']['source']
except KeyError:
imglink = ''
return {'image': imglink, 'tidbits': tidbits}

@command()
async def get(self, ctx: Context, name: str = None):
@commands.command()
async def get(self, ctx, name: str.title = None):
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.

You removed the type hinting for ctx. This will break things. Also, you can't type hint str.title.

Copy link
Copy Markdown
Author

@supposedly supposedly Mar 23, 2018

Choose a reason for hiding this comment

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

huh, what would the Context typehint do and/or break? (are you folks running a type checker?)

The str.title typehint is a converter -- see Rapptz/discord.py#1064 (bad pr on my part but it's there) and the documentation on converters. Converting to str is in fact redundant as far as ext.commands is concerned.

[BUT: I've also just realized I don't even want to convert with str.title(), because Wikipedia articles are titled in This case. Oops]

"""
Go online and fetch information about a snake

Expand All @@ -40,8 +77,10 @@ async def get(self, ctx: Context, name: str = None):
:param ctx: Context object passed from discord.py
:param name: Optional, the name of the snake to get information for - omit for a random snake
"""

# Any additional commands can be placed here. Be creative, but keep it to a reasonable amount!
d = await self.get_snek(name)
embed = discord.Embed(description='\n\n • '.join(d['tidbits']))
embed.set_thumbnail(url=d['image'])
await ctx.send(embed=embed)


def setup(bot):
Expand Down