BBC-News-Bot/src/bot.py
2023-07-07 07:44:28 +01:00

119 lines
3.0 KiB
Python

"""
The discord bot for the application.
"""
import os
import time
import logging
from datetime import datetime
import aiohttp
import discord
from bs4 import BeautifulSoup as bs4
from discord import Intents, Interaction, app_commands
from discord.ext import commands, tasks
from bbc_feeds import news
log = logging.getLogger(__name__)
EXTENSIONS_DIRECTORY = "src/extensions/"
class DiscordBot(commands.Bot):
def __init__(self):
super().__init__(command_prefix="-", intents=Intents.all())
async def sync_app_commands(self):
"""
Sync application commands.
"""
await self.wait_until_ready()
await self.tree.sync()
log.info("Application commands successfully synced")
async def on_ready(self):
"""
When the bot is ready.
"""
await self.sync_app_commands()
async def load_extensions(self):
"""
Load any extensions found in the extensions dictionary.
"""
for filename in os.listdir(EXTENSIONS_DIRECTORY):
if filename.endswith(".py"):
await self.load_extension(f"extensions.{filename[:-3]}")
class CommandsCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
# self.news_task.start()
async def story_to_embed(self, story) -> discord.Embed:
"""
Returns a discord.Embed object representing the given story.
Parameters
----------
story : _type_
_description_
Returns
-------
discord.Embed
_description_
"""
async with aiohttp.ClientSession() as session:
async with session.get(story.link) as response:
html = await response.text()
soup = bs4(html, "html.parser")
image_src = soup.select_one("picture > img").get("src")
embed = discord.Embed(
colour=discord.Colour.from_rgb(255, 0, 0),
title=story.title,
description=story.summary,
url=story.link,
timestamp=datetime.fromtimestamp(time.mktime(story.published_parsed)),
)
embed.set_image(url=image_src)
return embed
group = app_commands.Group(
name="news",
description="BBC News"
)
checked_news = set()
@group.command(name="latest")
async def get_latest_news(self, inter: Interaction, limit: int = 1):
"""
Provides the latest developments from BBC News.
"""
await inter.response.defer()
stories = news().all(limit=limit)
for story in stories:
embed = await self.story_to_embed(story)
await inter.followup.send(embed=embed)
@tasks.loop(minutes=15)
async def news_task(self):
story = news().all(limit=1)[0]
if story.link in self.checked_news:
return
self.checked_news.add(story.link)
embed = await self.story_to_embed(story)
channel = self.bot.get_channel(1057004889458348042)
await channel.send(embed=embed)