diff --git a/lenaverse_bot/commands/__init__.py b/lenaverse_bot/commands/__init__.py new file mode 100644 index 0000000..e1d8666 --- /dev/null +++ b/lenaverse_bot/commands/__init__.py @@ -0,0 +1,3 @@ +from . import advent, post, verein + +COMMANDS = post.COMMANDS + verein.COMMANDS + advent.COMMANDS diff --git a/lenaverse_bot/commands/advent.py b/lenaverse_bot/commands/advent.py new file mode 100644 index 0000000..4510d5b --- /dev/null +++ b/lenaverse_bot/commands/advent.py @@ -0,0 +1,97 @@ +import logging +from io import BytesIO + +import aiohttp +import discord + +from ..core.config import CONFIG + +_logger = logging.getLogger(__name__) + + +@discord.app_commands.command(name=CONFIG.command_prefix + "advent") +async def advent(interaction: discord.Interaction, day: int | None = None) -> None: + """ + Türchen vom Lenaisten-Adventskalender öffnen (https://advent.lenaisten.de) + """ + + _logger.debug( + f"User {interaction.user.name}({interaction.user.id}) used /advent (day: {day})" + ) + + async with aiohttp.ClientSession( + auth=aiohttp.BasicAuth(login="", password="") + ) as session: + if day is None: + # Kein Tag angegeben => neuesten Tag finden + + async with session.get( + "https://advent.lenaisten.de/api/user/doors" + ) as http_response: + if http_response.status != 200: + # user/doors Anfrage hat nicht geklappt + await interaction.response.send_message( + content="Fehler: Ich konnte das aktuelle Türchen nicht finden :zany_face: (Probier's nochmal?)", + # nur für ausführenden User + ephemeral=True, + ) + return + + if not isinstance(doors := await http_response.json(), list): + # user/doors Antwort falsches Format (keine Liste) + await interaction.response.send_message( + content="Fehler: Ich konnte das aktuelle Türchen nicht finden :sweat_smile: (Probier's nochmal?)", + ephemeral=True, + ) + return + + days: list[int] = [] + for door in doors: + if not isinstance(door, dict) or "day" not in door: + # user/doors Antwort falsches Format (Liste enthält falsche Daten) + await interaction.response.send_message( + content="Fehler: Ich konnte das aktuelle Türchen nicht finden :face_with_monocle: (Probier's nochmal?)", + ephemeral=True, + ) + return + + days.append(door["day"]) + + day = max(days) + + async with session.get( + f"https://advent.lenaisten.de/api/user/image_{day}" + ) as http_response: + reply_ephemeral = not CONFIG.ev_info.in_allowed_channel(interaction) + + if http_response.status == 401: + # Bild (noch) nicht verfügbar + await interaction.response.send_message( + content=f"Fehler: Tag {day} kann ich (noch?) nicht abrufen. Netter Versuch! :woman_technologist_tone2:", + ephemeral=reply_ephemeral, + ) + return + + if http_response.status != 200: + # Bild (noch) nicht verfügbar + await interaction.response.send_message( + content="Fehler: Ich konnte das Bild nicht herunterladen :sob: (Probier's nochmal?)", + ephemeral=True, + ) + return + + image = discord.File( + fp=BytesIO(await http_response.read()), + filename="advent.jpg", + ) + + await interaction.response.send_message( + content=f"Hier ist das Bild für Tag {day}!", + file=image, + ephemeral=reply_ephemeral, + ) + + +COMMANDS = [ + advent, +] diff --git a/lenaverse_bot/core/post.py b/lenaverse_bot/commands/post.py similarity index 96% rename from lenaverse_bot/core/post.py rename to lenaverse_bot/commands/post.py index f2632db..077d352 100644 --- a/lenaverse_bot/core/post.py +++ b/lenaverse_bot/commands/post.py @@ -4,7 +4,7 @@ from enum import Enum, auto import discord from discord import ui -from .config import CONFIG +from ..core.config import CONFIG _logger = logging.getLogger(__name__) @@ -111,7 +111,7 @@ async def post(interaction: discord.Interaction) -> None: f"User {interaction.user.name}({interaction.user.id}) tried to /post" ) await interaction.response.send_message( - content="Du bist nicht berechtigt, den `/post`-Befehl zu benutzen!", + content=f"Du bist nicht berechtigt, den `/{CONFIG.command_prefix}post`-Befehl zu benutzen!", # nur für ausführenden User ephemeral=True, ) diff --git a/lenaverse_bot/core/verein.py b/lenaverse_bot/commands/verein.py similarity index 75% rename from lenaverse_bot/core/verein.py rename to lenaverse_bot/commands/verein.py index 6a6f282..2161f5b 100644 --- a/lenaverse_bot/core/verein.py +++ b/lenaverse_bot/commands/verein.py @@ -3,16 +3,11 @@ import logging import discord -from .config import CONFIG, FileCommand, InfoCommand +from ..core.config import CONFIG, FileCommand, InfoCommand _logger = logging.getLogger(__name__) -def reply_private(interaction: discord.Interaction, name: str) -> bool: - _logger.debug(f"User {interaction.user.name}({interaction.user.id}) used /{name}") - return interaction.channel_id not in CONFIG.ev_info.channels - - @functools.singledispatch def make_command(command) -> discord.app_commands.Command: raise NotImplementedError @@ -25,11 +20,15 @@ def _(command: FileCommand) -> discord.app_commands.Command: description=command.description, ) async def cmd(interaction: discord.Interaction) -> None: + _logger.debug( + f"User {interaction.user.name}({interaction.user.id}) used FileCommand /{command.name}" + ) + if (file := await command.as_discord_file) is not None: await interaction.response.send_message( content=command.content, suppress_embeds=True, - ephemeral=reply_private(interaction, command.name), + ephemeral=not CONFIG.ev_info.in_allowed_channel(interaction), file=file, ) @@ -49,10 +48,14 @@ def _(command: InfoCommand) -> discord.app_commands.Command: description=command.description, ) async def cmd(interaction: discord.Interaction) -> None: + _logger.debug( + f"User {interaction.user.name}({interaction.user.id}) used InfoCommand /{command.name}" + ) + await interaction.response.send_message( content=command.content, suppress_embeds=True, - ephemeral=reply_private(interaction, command.name), + ephemeral=not CONFIG.ev_info.in_allowed_channel(interaction), ) return cmd diff --git a/lenaverse_bot/core/bot.py b/lenaverse_bot/core/bot.py index 55212d5..5057f96 100644 --- a/lenaverse_bot/core/bot.py +++ b/lenaverse_bot/core/bot.py @@ -2,7 +2,7 @@ import logging import discord -from . import post, verein +from ..commands import COMMANDS from .config import CONFIG _logger = logging.getLogger(__name__) @@ -16,8 +16,7 @@ class LenaverseBot(discord.Client): ) self.tree = discord.app_commands.CommandTree(self) - commands = post.COMMANDS + verein.COMMANDS - for command in commands: + for command in COMMANDS: self.tree.add_command(command) async def setup_hook(self): diff --git a/lenaverse_bot/core/config.py b/lenaverse_bot/core/config.py index 490c54d..eb5bdcb 100644 --- a/lenaverse_bot/core/config.py +++ b/lenaverse_bot/core/config.py @@ -68,6 +68,18 @@ class ClubInfo(BaseModel): fest: InfoCommand aktion: InfoCommand + def in_allowed_channel(self, interaction: discord.Interaction) -> bool: + if interaction.channel is None: + return False + + # öffentliche Antwort erlaubt in: + # - DM channels + # - "allowed" channels + is_dm_channel = isinstance(interaction.channel, discord.DMChannel) + is_listed = interaction.channel.id in self.channels + + return is_dm_channel or is_listed + class Config(BaseModel): discord_token: str