From 43120d9191c8c7627e097c3b5f1d920f6cb9f3ce Mon Sep 17 00:00:00 2001 From: Abigail Gold Date: Mon, 28 Oct 2019 00:23:56 -0400 Subject: [PATCH 1/2] add weather command, move solar weather to weather cog, change no subcommand in ae7qcog to send help. --- CHANGELOG.md | 1 + cogs/ae7qcog.py | 3 +- cogs/imagecog.py | 19 ----- cogs/weathercog.py | 140 ++++++++++++++++++++++++++++++++++ templates/template_options.py | 2 +- 5 files changed, 143 insertions(+), 22 deletions(-) create mode 100644 cogs/weathercog.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 481478c..91e00c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Rich lookup for AE7Q (callsigns only, more to come) - Rich lookup for QRZ, if a QRZ subscription is present - Timestamp and requester username and avatar are now shown on embeds +- Current and 3-Day Forecast terrestrial weather condition lookup commands ### Changed - Rewrote code to take advantage of discord.py's cogs - Moved most bot responses into embeds diff --git a/cogs/ae7qcog.py b/cogs/ae7qcog.py index 4304895..aa7eea6 100644 --- a/cogs/ae7qcog.py +++ b/cogs/ae7qcog.py @@ -31,8 +31,7 @@ class AE7QCog(commands.Cog): async def _ae7q_lookup(self, ctx: commands.Context): '''Look up a callsign, FRN, or Licensee ID on ae7q.com''' if ctx.invoked_subcommand is None: - await ctx.send('Invalid ae7q command passed\nPossible commands:' + - '`call`, `frn`, `lic` or `licensee`.') + await ctx.send_help(ctx.command) @_ae7q_lookup.command(name="call") async def _ae7q_call(self, ctx: commands.Context, callsign: str): diff --git a/cogs/imagecog.py b/cogs/imagecog.py index f52e963..922296f 100644 --- a/cogs/imagecog.py +++ b/cogs/imagecog.py @@ -56,25 +56,6 @@ class ImageCog(commands.Cog): await ctx.send(embed=embed, file=img) - @commands.command(name="cond", aliases=['condx']) - async def _band_conditions(self, ctx: commands.Context): - '''Posts an image of HF Band Conditions.''' - with ctx.typing(): - embed = discord.Embed(title='Current Solar Conditions', - colour=self.gs.colours.good, - timestamp=datetime.utcnow()) - async with aiohttp.ClientSession() as session: - async with session.get('http://www.hamqsl.com/solarsun.php') as resp: - if resp.status != 200: - embed.description = 'Could not download file...' - embed.colour = self.gs.colours.bad - else: - data = io.BytesIO(await resp.read()) - embed.set_image(url=f'attachment://condx.png') - embed.set_footer(text=ctx.author.name, - icon_url=str(ctx.author.avatar_url)) - await ctx.send(embed=embed, file=discord.File(data, 'condx.png')) - @commands.command(name="grayline", aliases=['greyline', 'grey', 'gray', 'gl']) async def _grayline(self, ctx: commands.Context): '''Posts a map of the current greyline, where HF propagation is the best.''' diff --git a/cogs/weathercog.py b/cogs/weathercog.py new file mode 100644 index 0000000..9217bdf --- /dev/null +++ b/cogs/weathercog.py @@ -0,0 +1,140 @@ +""" +Weather cog for qrm +--- +Copyright (C) 2019 Abigail Gold, 0x5c + +This file is part of discord-qrmbot and is released under the terms of the GNU +General Public License, version 2. +""" + +import io +from datetime import datetime +import re + +import discord +import discord.ext.commands as commands + +import aiohttp + + +class WeatherCog(commands.Cog): + wttr_units_regex = re.compile(r"\B-([cCfF])\b") + + def __init__(self, bot: commands.Bot): + self.bot = bot + self.gs = bot.get_cog("GlobalSettings") + + @commands.command(name="cond", aliases=['condx']) + async def _band_conditions(self, ctx: commands.Context): + '''Posts an image of HF Band Conditions.''' + with ctx.typing(): + embed = discord.Embed(title='Current Solar Conditions', + colour=self.gs.colours.good, + timestamp=datetime.utcnow()) + async with aiohttp.ClientSession() as session: + async with session.get('http://www.hamqsl.com/solarsun.php') as resp: + if resp.status != 200: + embed.description = 'Could not download file...' + embed.colour = self.gs.colours.bad + else: + data = io.BytesIO(await resp.read()) + embed.set_image(url=f'attachment://condx.png') + embed.set_footer(text=ctx.author.name, + icon_url=str(ctx.author.avatar_url)) + await ctx.send(embed=embed, file=discord.File(data, 'condx.png')) + + @commands.group(name="weather", aliases=['wttr']) + async def _weather_conditions(self, ctx: commands.Context): + '''Posts an image of Local Weather Conditions from [wttr.in](http://wttr.in/). + +*Supported location types:* + city name: `paris` + any location: `~Eiffel Tower` + Unicode name of any location in any language: `Москва` + airport code (3 letters): `muc` + domain name `@stackoverflow.com` + area codes: `12345` + GPS coordinates: `-78.46,106.79` + ''' + if ctx.invoked_subcommand is None: + await ctx.send_help(ctx.command) + + @_weather_conditions.command(name='forecast') + async def _weather_conditions_forecast(self, ctx: commands.Context, *, args: str): + '''Posts an image of Local Weather Conditions for the next three days from [wttr.in](http://wttr.in/). +See help for weather command for possible location types. Add a `-c` or `-f` to use Celcius or Fahrenheit.''' + with ctx.typing(): + try: + units_arg = re.search(self.wttr_units_regex, args).group(1) + except AttributeError: + units_arg = '' + if units_arg.lower() == 'f': + units = 'u' + elif units_arg.lower() == 'c': + units = 'm' + else: + units = '' + + loc = self.wttr_units_regex.sub('', args).strip() + + embed = discord.Embed(title=f'Weather Forecast for {loc}', + description='Data from [wttr.in](http://wttr.in/).', + colour=self.gs.colours.good, + timestamp=datetime.utcnow()) + loc = loc.replace(' ', '+') + async with aiohttp.ClientSession() as session: + async with session.get(f'http://wttr.in/{loc}_{units}pnFQ.png') as resp: + if resp.status != 200: + embed.description = 'Could not download file...' + embed.colour = self.gs.colours.bad + else: + data = io.BytesIO(await resp.read()) + loc = loc.replace('+', '') + loc = loc.replace('@', '') + loc = loc.replace('~', '') + embed.set_image(url=f'attachment://{loc}_{units}pnFQ.png') + embed.set_footer(text=ctx.author.name, + icon_url=str(ctx.author.avatar_url)) + await ctx.send(embed=embed, file=discord.File(data, f'{loc}_{units}pnFQ.png')) + + @_weather_conditions.command(name='now') + async def _weather_conditions_now(self, ctx: commands.Context, *, args: str): + '''Posts an image of current Local Weather Conditions from [wttr.in](http://wttr.in/). +See help for weather command for possible location types. Add a `-c` or `-f` to use Celcius or Fahrenheit.''' + with ctx.typing(): + try: + units_arg = re.search(self.wttr_units_regex, args).group(1) + except AttributeError: + units_arg = '' + if units_arg.lower() == 'f': + units = 'u' + elif units_arg.lower() == 'c': + units = 'm' + else: + units = '' + + loc = self.wttr_units_regex.sub('', args).strip() + + embed = discord.Embed(title=f'Current Weather for {loc}', + description='Data from [wttr.in](http://wttr.in/).', + colour=self.gs.colours.good, + timestamp=datetime.utcnow()) + loc = loc.replace(' ', '+') + async with aiohttp.ClientSession() as session: + async with session.get(f'http://wttr.in/{loc}_0{units}pnFQ.png') as resp: + if resp.status != 200: + embed.description = 'Could not download file...' + embed.colour = self.gs.colours.bad + else: + data = io.BytesIO(await resp.read()) + loc = loc.replace('+', '') + loc = loc.replace('@', '') + loc = loc.replace('~', '') + embed.set_image(url=f'attachment://{loc}_0{units}pnFQ.png') + embed.set_footer(text=ctx.author.name, + icon_url=str(ctx.author.avatar_url)) + await ctx.send(embed=embed, file=discord.File(data, f'{loc}_0{units}pnFQ.png')) + + +def setup(bot: commands.Bot): + bot.add_cog(WeatherCog(bot)) diff --git a/templates/template_options.py b/templates/template_options.py index f9a9b39..ce21e4c 100644 --- a/templates/template_options.py +++ b/templates/template_options.py @@ -27,7 +27,7 @@ owners_uids = (200102491231092736,) # The cogs to load when running the bot. cogs = ['basecog', 'morsecog', 'funcog', 'gridcog', 'hamcog', 'imagecog', - 'studycog', 'ae7qcog', 'qrzcog'] + 'studycog', 'ae7qcog', 'qrzcog', 'weathercog'] # The text to put in the "playing" status. game = 'with lids on 7.200' From c4b83bdb419e7e1141a9ae96374829fe2def6211 Mon Sep 17 00:00:00 2001 From: Abigail Gold <5366828+classabbyamp@users.noreply.github.com> Date: Mon, 28 Oct 2019 14:32:59 -0400 Subject: [PATCH 2/2] Update CHANGELOG.md Co-Authored-By: 0x5c <0x5c.dev@gmail.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91e00c9..0a15db8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Rich lookup for AE7Q (callsigns only, more to come) - Rich lookup for QRZ, if a QRZ subscription is present - Timestamp and requester username and avatar are now shown on embeds -- Current and 3-Day Forecast terrestrial weather condition lookup commands +- Current and 3-Day Forecast terrestrial weather conditions lookup commands ### Changed - Rewrote code to take advantage of discord.py's cogs - Moved most bot responses into embeds