Skip to content

Commit

Permalink
Merge pull request #214 from idoneam/dev
Browse files Browse the repository at this point in the history
Release v1.0.0: Out of beta
  • Loading branch information
jidicula authored Nov 27, 2019
2 parents 3c66e7a + 2f88e31 commit eadc81d
Show file tree
Hide file tree
Showing 10 changed files with 334 additions and 277 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ ENV/
.mypy_cache/

# configuration files
*.ini
**/*.ini

# other
*~
Expand Down
12 changes: 10 additions & 2 deletions Main.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,16 @@

# List the extensions (modules) that should be loaded on startup.
startup = [
"cogs.reminder", "cogs.memes", "cogs.helpers", "cogs.mod", "cogs.score",
"cogs.quotes", "cogs.images", "cogs.currency"
"cogs.currency",
"cogs.helpers",
"cogs.images",
"cogs.info",
"cogs.memes",
"cogs.mod",
"cogs.quotes",
"cogs.reminder",
"cogs.score",
"cogs.subscribers",
]

# TODO: SHOULD BE DB
Expand Down
4 changes: 2 additions & 2 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ name = "pypi"
beautifulsoup4 = "==4.8.0"
sympy = "==1.4.0"
requests = ">=2.20.0"
tabulate = "==0.7.7"
discord.py = "==1.2.3"
tabulate = "==0.8.6"
discord.py = "==1.2.5"
opencv-python = "*"
pytz = "*"
mpmath = "*"
Expand Down
191 changes: 91 additions & 100 deletions Pipfile.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,12 @@ You must set certain values in the `config.ini` file, in particular your Discor
* `GCWeatherAlertURL`: Government of Canada weather alerts URL. **Region-specific.**
* `WttrINTemplate`: [http://wttr.in/](http://wttr.in/) URL template. **Region-specific.**
* `TepidURL`: [TEPID](https://github.com/ctf/TEPID-Server) screensaver endpoint for printer status.
* `[Subscribers]`
* `FoodRecallChannel`: Channel where you want CFIA recall notices posted.
* `FoodRecallLocationFilter`: Regions you want to receive CFIA recall notices for.
* `FoodSpottingChannel`: Channel where you want foodspotting posts to be sent, ideally in a dedicated channel.
* `NoFoodSpottingRole`: Name of role assigned to abusers of the foodspotting command that will prevent them from using it.
* `MetroStatusChannel`: Channel where you want metro status alerts to be sent, ideally in a dedicated channel with opt-in read permissions for users.
* `[Currency]`
* `Name`: The name of the bot currency.
* `Symbol`: The currency's symbol (e.g. `$`).
Expand Down
165 changes: 75 additions & 90 deletions cogs/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import discord
from discord.ext import commands
from discord import utils
import asyncio

# URL access and parsing
from bs4 import BeautifulSoup
Expand All @@ -38,8 +37,6 @@
import math
import time
import datetime
import pickle
import feedparser
import random
from .utils.paginator import Pages
from .utils.requests import fetch
Expand All @@ -64,51 +61,6 @@ class Helpers(commands.Cog):
def __init__(self, bot):
self.bot = bot

async def cfia_rss(self):
# Written by @jidicula
"""
Co-routine that periodically checks the CFIA Health Hazard Alerts RSS
feed for updates.
"""
await self.bot.wait_until_ready()
while not self.bot.is_closed():
recall_channel = utils.get(self.bot.get_guild(
self.bot.config.server_id).text_channels,
name=self.bot.config.recall_channel)
newest_recalls = feedparser.parse(CFIA_FEED_URL)['entries']
try:
id_unpickle = open("pickles/recall_tag.obj", 'rb')
recalls = pickle.load(id_unpickle)
id_unpickle.close()
except Exception:
recalls = {}
new_recalls = False
for recall in newest_recalls:
recall_id = recall['id']
if recall_id not in recalls:
new_recalls = True
recalls[recall_id] = ""
recall_warning = discord.Embed(title=recall['title'],
description=recall['link'])
soup = BeautifulSoup(recall['summary'], "html.parser")
try:
img_url = soup.img['src']
summary = soup.p.find_parent().text.strip()
except Exception:
img_url = ""
summary = recall['summary']
if re.search(self.bot.config.recall_filter, summary,
re.IGNORECASE):
recall_warning.set_image(url=img_url)
recall_warning.add_field(name="Summary", value=summary)
await recall_channel.send(embed=recall_warning)
if new_recalls:
# Pickle newly added IDs
id_pickle = open("pickles/recall_tag.obj", 'wb')
pickle.dump(recalls, id_pickle)
id_pickle.close()
await asyncio.sleep(12 * 3600) # run every 12 hours

@commands.command(aliases=['exams'])
async def exam(self, ctx):
"""Retrieves the exam schedule link from McGill's Exam website."""
Expand All @@ -131,58 +83,85 @@ async def exam(self, ctx):
async def weather(self, ctx):
"""Retrieves current weather conditions.
Data taken from http://weather.gc.ca/city/pages/qc-147_metric_e.html"""
def retrieve_string(label):
return soup.find(
"dt", string=label).find_next_sibling().get_text().strip()

await ctx.trigger_typing()

r = await fetch(self.bot.config.gc_weather_url, "content")

soup = BeautifulSoup(r, "html.parser")
# Get date
observed_label = soup.find("dt", string="Date: ")
observed_string = retrieve_string("Date: ")
# Get temperature
temperature_label = soup.find("dt", string="Temperature:")
temperature_string = retrieve_string("Temperature:")
# Get condition
condition_label = soup.find("dt", string="Condition:")
condition_string = retrieve_string("Condition:")
# Get pressure
pressure_label = soup.find("dt", string="Pressure:")
pressure_string = retrieve_string("Pressure:")
# Get tendency
tendency_label = soup.find("dt", string="Tendency:")
tendency_string = retrieve_string("Tendency:")
# Get wind
wind_label = soup.find("dt", string="Wind:")
# Get windchill, only if it can be found.

try:
windchill_label = soup.find("a", string="Wind Chill")
windchill = windchill_label.find_next().get_text().strip(
) + u"\xb0C"
except Exception:
windchill = u"N/A"

weather_now = discord.Embed(
title='Current Weather',
description='Conditions observed at %s' %
observed_label.find_next_sibling().get_text().rstrip(),
colour=0x7EC0EE)
weather_now.add_field(
name="Temperature",
value=temperature_label.find_next_sibling().get_text().strip(),
inline=True)
weather_now.add_field(
name="Condition",
value=condition_label.find_next_sibling().get_text().strip(),
inline=True)
weather_now.add_field(
name="Pressure",
value=pressure_label.find_next_sibling().get_text().strip(),
inline=True)
weather_now.add_field(
name="Tendency",
value=tendency_label.find_next_sibling().get_text().strip(),
inline=True)
weather_now.add_field(
name="Wind Speed",
value=wind_label.find_next_sibling().get_text().strip(),
inline=True)
weather_now.add_field(name="Wind Chill", value=windchill, inline=True)
wind_string = retrieve_string("Wind:")
# Get relative humidity
humidity_string = retrieve_string("Humidity:")
# Get "Feels like" temperature using formula from MetService (Meteorological
# Service of New Zealand), which uses the standard formula for windchill from
# Environment Canada for temperatures of 10°C and less (or the normal
# temperature if the wind speed is less than 5 km/h), the Australian apparent
# temperature for temperatures of 14°C and more (or the normal temperature if
# it is higher), and a linear roll-off of the wind chill between 10°C and 14°C
# (https://blog.metservice.com/FeelsLikeTemp)
temperature = float(
re.search(r"-?\d+\.\d", temperature_string).group())
wind_speed_kph = float(re.search(r"\d+", wind_string).group())
wind_speed_mps = wind_speed_kph * 1000 / 3600
humidity = float(re.search(r"\d+", humidity_string).group())
wind_chill = (13.12 + 0.6215 * temperature -
11.37 * wind_speed_kph**0.16 +
0.3965 * temperature * wind_speed_kph**0.16)
vapour_pressure = humidity / 100 * 6.105 * math.exp(
(17.27 * temperature) / (237.7 + temperature))
apparent_temperature = (temperature + 0.33 * vapour_pressure -
0.7 * wind_speed_mps - 4.00)
feels_like = temperature
if temperature <= 10:
if wind_speed_kph >= 5:
feels_like = wind_chill
elif temperature >= 14:
if apparent_temperature > temperature:
feels_like = apparent_temperature
else:
if wind_speed_kph >= 5:
feels_like = temperature - ((temperature - wind_chill) *
(14 - temperature)) / 4

feels_like = round(feels_like, 1)
feels_like_string = "{}°C".format(feels_like)

weather_now = discord.Embed(title='Current Weather',
description='Conditions observed at %s' %
observed_string,
colour=0x7EC0EE)
weather_now.add_field(name="Temperature",
value=temperature_string,
inline=True)
weather_now.add_field(name="Condition",
value=condition_string,
inline=True)
weather_now.add_field(name="Pressure",
value=pressure_string,
inline=True)
weather_now.add_field(name="Tendency",
value=tendency_string,
inline=True)
weather_now.add_field(name="Wind Speed",
value=wind_string,
inline=True)
weather_now.add_field(name="Feels like",
value=feels_like_string,
inline=True)

# Weather alerts

Expand Down Expand Up @@ -419,8 +398,15 @@ async def tex(self, ctx, *, query: str):
tex += "\\[" + sp[2 * i + 1] + "\\]"

buf = BytesIO()
LATEX_PREAMBLE = ("\\documentclass[varwidth,12pt]{standalone}"
"\\usepackage{alphabeta}"
"\\usepackage[utf8]{inputenc}"
"\\usepackage[LGR,T1]{fontenc}"
"\\usepackage{amsmath,amsfonts,lmodern}"
"\\begin{document}")
preview(
tex,
preamble=LATEX_PREAMBLE,
viewer="BytesIO",
outputbuffer=buf,
euler=False,
Expand Down Expand Up @@ -583,4 +569,3 @@ async def colour(self, ctx, *, arg: str):

def setup(bot):
bot.add_cog(Helpers(bot))
bot.loop.create_task(Helpers(bot).cfia_rss())
Loading

0 comments on commit eadc81d

Please sign in to comment.