Skip to content
This repository was archived by the owner on Mar 14, 2021. It is now read-only.

Team 17 #8

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open
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
b312786
just add some pass stuff
SharpBit Mar 23, 2018
31fe5d8
Merge pull request #1 from discord-python/master
SharpBit Mar 23, 2018
f92cf5e
some startup stuff
SharpBit Mar 23, 2018
d04759c
Merge branch 'master' of https://github.com/SharpBit/code-jam-1
SharpBit Mar 23, 2018
91cfb2d
fix bs4 req
SharpBit Mar 23, 2018
6dd7aef
remove that
SharpBit Mar 23, 2018
c865044
right thing to run
SharpBit Mar 23, 2018
e830c95
create the soup from the info source
SharpBit Mar 23, 2018
80273f6
rough estimate of what it should look like
SharpBit Mar 24, 2018
36ace30
@pikuhana can u do something
SharpBit Mar 24, 2018
9816692
Merge pull request #2 from discord-python/master
SharpBit Mar 24, 2018
2d743c8
Use image from OGP tag, remove unused methods.
jchristgit Mar 24, 2018
b77b7fe
test
SharpBit Mar 24, 2018
49f5251
Merge branch 'master' of https://github.com/SharpBit/code-jam-1
SharpBit Mar 24, 2018
f915d90
image (most work) and description
SharpBit Mar 24, 2018
a552543
Attach URL and location map.
jchristgit Mar 24, 2018
3234d57
did you know command
SharpBit Mar 25, 2018
3f56b6c
remove map image for now
SharpBit Mar 25, 2018
dfd3175
if python: send language
SharpBit Mar 25, 2018
0ff0f42
Fix location map image URL.
jchristgit Mar 25, 2018
ddc6e4e
Still more bugs...
SharpBit Mar 25, 2018
9edf8c9
Added a TicTacToe game stub.
jchristgit Mar 25, 2018
97e0e9d
fix some requests and travis stuff
SharpBit Mar 25, 2018
adafa48
redo the bot.get python
SharpBit Mar 25, 2018
7033463
Revert "Added a TicTacToe game stub."
jchristgit Mar 25, 2018
cca57c4
completely remove
SharpBit Mar 25, 2018
3f91775
fix flake8 linting import order
SharpBit Mar 25, 2018
b712a24
map region works all the time!
SharpBit Mar 25, 2018
5850ddb
success rate of images has gone up!
SharpBit Mar 25, 2018
256d4e1
fix flake8
SharpBit Mar 25, 2018
0854cb1
fix requested changes
SharpBit 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
2 changes: 2 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ name = "pypi"
aiodns = "*"
aiohttp = "<2.3.0,>=2.0.0"
websockets = ">=4.0,<5.0"
"beautifulsoup4" = "*"
lxml = "*"

[dev-packages]
"flake8" = "*"
Expand Down
51 changes: 47 additions & 4 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions bot/cogs/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ def __init__(self, bot: AutoShardedBot):
self.bot = bot

async def on_ready(self):
log.info('Signed in as:')
log.info('--------------')
log.info(f'Username: {self.bot.user.name}')
log.info(f'User ID: {self.bot.user.id}')
log.info('--------------')
log.info('Serving Team 17 in Code Jam 1!')
log.info('--------------')
log.info("Bot connected!")


Expand Down
158 changes: 155 additions & 3 deletions bot/cogs/snakes.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
# coding=utf-8
import logging
from difflib import get_close_matches
from random import choice
from typing import Any, Dict

from aiohttp import ClientSession

from bs4 import BeautifulSoup

import discord
from discord.ext.commands import AutoShardedBot, Context, command

from bot.selectors import (
ALT_IMG_SELECTOR,
DID_YOU_KNOW_SELECTOR,
SCIENTIFIC_NAME_SELECTOR,
SNAKE_IMG_SELECTOR,
SNEK_MAP_SELECTOR
)

log = logging.getLogger(__name__)

PYTHON_INFO = {
'name': 'Python',
'scientific-name': 'Pseudo anguis',
'image-url': 'https://www.python.org/static/community_lopython-logo-master-v3-TM.png',
'url': 'https://en.wikipedia.org/wiki/Python_(programming_language)',
'map-url': 'https://ih0.redbubble.net/image.80621508.8flat,800x800,075,t.u1.jpg',
'description': 'Python is an interpreted high-level programmlanguage '
'for general-purpose programming. '
'Created by Guido van Rossum and first released1991, '
'Python has a design philosophy that emphasizes creadability, '
'notably using significant whitespace.'
}


class Snakes:
"""
Expand All @@ -15,6 +43,49 @@ class Snakes:
def __init__(self, bot: AutoShardedBot):
self.bot = bot

async def on_ready(self):
self.session = ClientSession(loop=self.bot.loop)
self.info_url = 'https://snake-facts.weebly.com/'
log.info('Session created.')

with open('./snakes.txt', encoding='utf-8') as f:
self.sneks = f.read().split('\n')
for i, snek in enumerate(self.sneks):
self.sneks[i] = snek.replace('\u200b', '').replace('\ufeff', '')
log.info('Snakes loaded.')

def no_sneks_found(self, name: str) -> discord.Embed:
"""Helper function if the snake was not found in the directory."""
em = discord.Embed(
title='No snake found.',
color=discord.Color.green()
)

snakes = get_close_matches(name, self.sneks)

if snakes:
em.description = 'Did you mean...\n'
em.description += '\n'.join(f'`{x}`' for x in snakes)
else:
snakes = 'https://github.com/SharpBit/code-jam-1/blob/master/snakes.txt'
em.description = f'No close matches found. Click [here]({snakes}) for the list of available snakes.'

return em

def format_info(self, data: dict, color=discord.Color.green()) -> discord.Embed:
"""Formats the info with the given data."""
em = discord.Embed(
title=f"{data['name']} ({data['scientific-name']})",
description=data['description'],
color=color,
url=data['url']
)

em.set_image(url=data['image-url'])
em.set_thumbnail(url=data['map-url'])

return em

async def get_snek(self, name: str = None) -> Dict[str, Any]:
"""
Go online and fetch information about a snake
Expand All @@ -28,9 +99,72 @@ 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
"""
if name:
if name not in self.sneks:
return self.no_sneks_found(name)
else:
name = choice(self.sneks)

@command()
async def get(self, ctx: Context, name: str = None):
snake = name.lower().replace(' ', '-').replace("'", '')
url = f'{self.info_url}{snake}.html'

async with self.session.get(url) as resp:
info = await resp.read()
soup = BeautifulSoup(info, 'lxml')

for x in range(1, 7):
try:
img = soup.select(SNAKE_IMG_SELECTOR.format(x))[0]['src']
break
except IndexError:
continue
try:
img = img[1:]
except UnboundLocalError:
img = soup.select(ALT_IMG_SELECTOR)[0]['src'][1:]

names = soup.find('td', class_='wsite-multicol-col')
sci_name = soup.select(SCIENTIFIC_NAME_SELECTOR)[0].text.strip()
description_tag = soup.find(attrs={'property': {'og:description'}})

for x in range(1, 7):
try:
location_map = soup.select(SNEK_MAP_SELECTOR.format(x))[0]['src']
break
except IndexError:
continue

info = {
'name': names.h1.string,
'scientific-name': sci_name,
'image-url': f'{self.info_url}{img}',
'map-url': f'{self.info_url}{location_map[1:]}',
'description': description_tag['content'],
'url': url
}

return info

async def get_snek_fact(self) -> discord.Embed:
"""Helper function to get a snake fact."""
page = choice(self.sneks).replace(' ', '-').replace("'", '')
url = f'{self.info_url}{page}.html'

async with self.session.get(url) as resp:
response = await resp.read()
soup = BeautifulSoup(response, 'lxml')
fact = soup.select(DID_YOU_KNOW_SELECTOR)[0].text

em = discord.Embed(
title='Did you know?',
description=fact[13:],
color=discord.Color.green()
)

return em

@command(aliases=['snakes.get', 'snakes.get()', 'get()'])
async def get(self, ctx: Context, *, name: str = None):
"""
Go online and fetch information about a snake

Expand All @@ -40,8 +174,26 @@ 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
"""
# Sends info about the programming language
if name:
if name.lower() == 'python':
em = self.format_info(PYTHON_INFO, discord.Color.blurple())
return await ctx.send(embed=em)
data = await self.get_snek(name)
# if the snake is not found
if isinstance(data, discord.Embed):
return await ctx.send(embed=data)
# format the given data
em = self.format_info(data)
await ctx.send(embed=em)

# Any additional commands can be placed here. Be creative, but keep it to a reasonable amount!
@command(aliases=['getsnekfact', 'snekfact()', 'get_snek_fact()'])
async def snekfact(self, ctx: Context):
"""
Gets a randomsnek fact from the "Did you know?" cards
that the website has on the right hand side.
"""
await ctx.send(embed=await self.get_snek_fact())


def setup(bot):
Expand Down
25 changes: 25 additions & 0 deletions bot/selectors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
ALT_IMG_SELECTOR = (
'#wsite-content > div:nth-of-type(2) > div > div > table > '
'tbody > tr > td:nth-of-type(1) > div:nth-of-type(5) > div > a > img'
)

DID_YOU_KNOW_SELECTOR = (
'#wsite-content > div:nth-of-type(2) > div > div > table > '
'tbody > tr > td:nth-of-type(2) > div:nth-of-type(1)'
)

SNAKE_IMG_SELECTOR = (
'#wsite-content > div:nth-of-type(2) > div > div > table > '
'tbody > tr > td:nth-of-type(1) > div:nth-of-type(4) > div > div > '
'table > tbody > tr > td:nth-of-type({0}) > div > div > a > img'
)

SCIENTIFIC_NAME_SELECTOR = (
"#wsite-content > div:nth-of-type(1) > div > div > "
"table > tbody > tr > td:nth-of-type(1) > div:nth-of-type(2)"
)

SNEK_MAP_SELECTOR = (
"#wsite-content > div:nth-of-type(2) > div > div > table > "
"tbody > tr > td:nth-of-type(2) > div:nth-of-type({0}) > div > a > img"
)
2 changes: 1 addition & 1 deletion run.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
">>> ", ">> ", "> ",
">>>", ">>", ">"
), # Order matters (and so do commas)
activity=Game(name="Help: bot.help()"),
activity=Game(name="with snekky sneks"),
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably a bit user-unfriendly, but it's fine in this case. :P

Copy link
Author

Choose a reason for hiding this comment

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

still mentionable /shrug

help_attrs={"aliases": ["help()"]},
formatter=Formatter()
)
Expand Down
Loading