From 4be2eaff1f19046f555fe61568352ce38643b127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn-Michael=20Miehe?= Date: Sat, 2 Dec 2023 18:18:35 +0100 Subject: [PATCH 1/5] allow public/persistent posts in DM channels --- lenaverse_bot/core/verein.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lenaverse_bot/core/verein.py b/lenaverse_bot/core/verein.py index 6a6f282..d750eaf 100644 --- a/lenaverse_bot/core/verein.py +++ b/lenaverse_bot/core/verein.py @@ -10,7 +10,15 @@ _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 + + # öffentliche Antwort in DM channels und in "allowed" channels + in_dm_channel = interaction.channel is not None and isinstance( + interaction.channel, discord.DMChannel + ) + in_allowed_channel = interaction.channel_id in CONFIG.ev_info.channels + + # private Antwort sonst + return not (in_dm_channel or in_allowed_channel) @functools.singledispatch From 491723fc3b294861c03f3dc57f890a570c67b343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn-Michael=20Miehe?= Date: Sat, 2 Dec 2023 23:56:11 +0100 Subject: [PATCH 2/5] move commands into package --- lenaverse_bot/commands/__init__.py | 3 +++ lenaverse_bot/{core => commands}/post.py | 2 +- lenaverse_bot/{core => commands}/verein.py | 2 +- lenaverse_bot/core/bot.py | 5 ++--- 4 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 lenaverse_bot/commands/__init__.py rename lenaverse_bot/{core => commands}/post.py (99%) rename lenaverse_bot/{core => commands}/verein.py (97%) diff --git a/lenaverse_bot/commands/__init__.py b/lenaverse_bot/commands/__init__.py new file mode 100644 index 0000000..c2015d8 --- /dev/null +++ b/lenaverse_bot/commands/__init__.py @@ -0,0 +1,3 @@ +from . import post, verein + +COMMANDS = post.COMMANDS + verein.COMMANDS diff --git a/lenaverse_bot/core/post.py b/lenaverse_bot/commands/post.py similarity index 99% rename from lenaverse_bot/core/post.py rename to lenaverse_bot/commands/post.py index f2632db..27d1db5 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__) diff --git a/lenaverse_bot/core/verein.py b/lenaverse_bot/commands/verein.py similarity index 97% rename from lenaverse_bot/core/verein.py rename to lenaverse_bot/commands/verein.py index d750eaf..c3cbeef 100644 --- a/lenaverse_bot/core/verein.py +++ b/lenaverse_bot/commands/verein.py @@ -3,7 +3,7 @@ import logging import discord -from .config import CONFIG, FileCommand, InfoCommand +from ..core.config import CONFIG, FileCommand, InfoCommand _logger = logging.getLogger(__name__) 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): From c913e63f51afbf910c77297bd3bb6235ce7c441f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn-Michael=20Miehe?= Date: Sun, 3 Dec 2023 00:00:16 +0100 Subject: [PATCH 3/5] /post fail message --- lenaverse_bot/commands/post.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lenaverse_bot/commands/post.py b/lenaverse_bot/commands/post.py index 27d1db5..077d352 100644 --- a/lenaverse_bot/commands/post.py +++ b/lenaverse_bot/commands/post.py @@ -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, ) From 385999a2f314ecdecbc2a6e20701c6ba53daf2fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn-Michael=20Miehe?= Date: Sun, 3 Dec 2023 00:38:14 +0100 Subject: [PATCH 4/5] verein.reply_private -> ClubInfo.is_allowed --- lenaverse_bot/commands/verein.py | 25 ++++++++++--------------- lenaverse_bot/core/config.py | 12 ++++++++++++ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/lenaverse_bot/commands/verein.py b/lenaverse_bot/commands/verein.py index c3cbeef..2161f5b 100644 --- a/lenaverse_bot/commands/verein.py +++ b/lenaverse_bot/commands/verein.py @@ -8,19 +8,6 @@ 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}") - - # öffentliche Antwort in DM channels und in "allowed" channels - in_dm_channel = interaction.channel is not None and isinstance( - interaction.channel, discord.DMChannel - ) - in_allowed_channel = interaction.channel_id in CONFIG.ev_info.channels - - # private Antwort sonst - return not (in_dm_channel or in_allowed_channel) - - @functools.singledispatch def make_command(command) -> discord.app_commands.Command: raise NotImplementedError @@ -33,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, ) @@ -57,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/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 From 47789f920a6efacdee6e0a2044282792e8c5eb49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn-Michael=20Miehe?= Date: Sun, 3 Dec 2023 00:52:26 +0100 Subject: [PATCH 5/5] command /advent --- lenaverse_bot/commands/__init__.py | 4 +- lenaverse_bot/commands/advent.py | 97 ++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 lenaverse_bot/commands/advent.py diff --git a/lenaverse_bot/commands/__init__.py b/lenaverse_bot/commands/__init__.py index c2015d8..e1d8666 100644 --- a/lenaverse_bot/commands/__init__.py +++ b/lenaverse_bot/commands/__init__.py @@ -1,3 +1,3 @@ -from . import post, verein +from . import advent, post, verein -COMMANDS = post.COMMANDS + verein.COMMANDS +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, +]