weather cog, including forecasts and location id
This commit is contained in:
parent
2f9bcec566
commit
ac1a761db7
136
src/extensions/weather.py
Normal file
136
src/extensions/weather.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
"""
|
||||||
|
Weather Cog.
|
||||||
|
WIP.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
|
import discord
|
||||||
|
from discord import app_commands, Interaction
|
||||||
|
from discord.ext import commands, tasks
|
||||||
|
from urllib.parse import quote
|
||||||
|
from bs4 import BeautifulSoup as bs4
|
||||||
|
|
||||||
|
from bbc_feeds import weather as weather_api
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class WeatherCog(commands.Cog):
|
||||||
|
"""
|
||||||
|
Weather cog is used to deliver localised weather information to dedicated discord channels.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
self.weather_task.start()
|
||||||
|
|
||||||
|
@tasks.loop(minutes=15)
|
||||||
|
async def weather_task(self):
|
||||||
|
"""
|
||||||
|
Send weather information to the assigned weather channels.
|
||||||
|
"""
|
||||||
|
|
||||||
|
log.info("doing weather task")
|
||||||
|
|
||||||
|
async def get_weather_embeds(self, location_id: int, limit: int) -> list[discord.Embed]:
|
||||||
|
"""
|
||||||
|
Returns a list of discord embeds containing weather data for the given location.
|
||||||
|
"""
|
||||||
|
|
||||||
|
log.info(f"getting weather for location {location_id}")
|
||||||
|
|
||||||
|
forecasts = weather_api().forecast(location_id, limit=limit)
|
||||||
|
if not forecasts:
|
||||||
|
return [
|
||||||
|
discord.Embed(
|
||||||
|
title="Weather Forecast Not Found",
|
||||||
|
description=f"I could not find the weather forecast for `{location_id}` :(",
|
||||||
|
colour=discord.Colour.red()
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
return [
|
||||||
|
discord.Embed(
|
||||||
|
title = forecast.title.split(", Minimum Temp")[0],
|
||||||
|
description=forecast.summary.replace(", ", "\n"),
|
||||||
|
url=forecast.link,
|
||||||
|
colour=discord.Colour.from_str("#FFFFFF")
|
||||||
|
)
|
||||||
|
for forecast in forecasts
|
||||||
|
]
|
||||||
|
|
||||||
|
weather_group = app_commands.Group(name="weather", description="Weather related commands")
|
||||||
|
channels_group = app_commands.Group(parent=weather_group, name="channels", description="Weather channel commands")
|
||||||
|
|
||||||
|
@weather_group.command(name="now")
|
||||||
|
async def get_weather_now(self, inter: Interaction, location_id: int):
|
||||||
|
"""
|
||||||
|
Returns the current weather in your local area.
|
||||||
|
"""
|
||||||
|
|
||||||
|
embeds = await self.get_weather_embeds(location_id, limit=1)
|
||||||
|
await inter.response.send_message(embeds=embeds)
|
||||||
|
|
||||||
|
@weather_group.command(name="tomorrow")
|
||||||
|
async def get_weather_tomorrow(self, inter: Interaction, location_id: int):
|
||||||
|
"""
|
||||||
|
Returns tomorrows weather in your local area.
|
||||||
|
"""
|
||||||
|
|
||||||
|
embed = (await self.get_weather_embeds(location_id, limit=2))[1]
|
||||||
|
await inter.response.send_message(embed=embed)
|
||||||
|
|
||||||
|
@weather_group.command(name="3-days")
|
||||||
|
async def get_weather_week(self, inter: Interaction, location_id: int):
|
||||||
|
"""
|
||||||
|
Returns the next 3 days worth of weather in your local area.
|
||||||
|
"""
|
||||||
|
|
||||||
|
embeds = await self.get_weather_embeds(location_id, limit=3)
|
||||||
|
await inter.response.send_message(embeds=embeds)
|
||||||
|
|
||||||
|
@weather_group.command(name="location-id")
|
||||||
|
async def get_weather_location_id(self, inter: Interaction, location_name: str):
|
||||||
|
"""
|
||||||
|
Returns a location ID used to identify weather in your local area.
|
||||||
|
"""
|
||||||
|
|
||||||
|
await inter.response.defer()
|
||||||
|
|
||||||
|
result_string = ""
|
||||||
|
|
||||||
|
safe_location = quote(location_name)
|
||||||
|
get_url = f"https://www.bbc.co.uk/weather/search?s={safe_location}"
|
||||||
|
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get(get_url) as response:
|
||||||
|
html = await response.text()
|
||||||
|
|
||||||
|
soup = bs4(html, "html.parser")
|
||||||
|
anchors = soup.select(".location-search-results__result__link")
|
||||||
|
|
||||||
|
for anchor in anchors:
|
||||||
|
location_id = anchor.get("href")
|
||||||
|
result_string += f"\n`{location_id}` {anchor.text}"
|
||||||
|
|
||||||
|
if result_string:
|
||||||
|
output_string = f"Here is what I found from that search:\n{result_string}"
|
||||||
|
else:
|
||||||
|
output_string = "I couldn't find any location ID's from that search"
|
||||||
|
|
||||||
|
await inter.followup.send(output_string)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async def setup(bot):
|
||||||
|
"""
|
||||||
|
Setup the weather cog with the bot.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cog = WeatherCog(bot)
|
||||||
|
await bot.add_cog(cog)
|
Loading…
x
Reference in New Issue
Block a user