Files
discord-heidi/heidi_helpers.py
Christoph Urlacher c2847de7dd
All checks were successful
Build Heidi Docker image / build-docker (push) Successful in 14s
Add instantbuttons command + make responses ephemeral
/instantbuttons displays a soundboard via a button ui
2023-12-09 19:51:28 +01:00

106 lines
3.1 KiB
Python

import asyncio
import functools
from typing import Union
import discord
from discord import Interaction, VoiceChannel, Member
from heidi_constants import *
print("Debug: Importing heidi_helpers.py")
# Checks -----------------------------------------------------------------------------------------
# 1. @enforce_channel(ID) is added to a function, which evaluates to decorate with the channel_id in its closure
# 2. The function is passed to decorate(function),
def enforce_channel(channel_id):
"""
Only run a function if called from the correct channel.
"""
def decorate(function):
@functools.wraps(function)
async def wrapped(*args, **kwargs):
"""
Sends an interaction response if the interaction is not triggered from the heidi_spam channel.
"""
interaction: Interaction = args[0]
# Do not call the decorated function if the channel_id doesn't match
if not interaction.channel_id == channel_id:
await interaction.response.send_message("Heidi sagt: Geh in heidi_spam du dulli", ephemeral=True)
return
await function(*args, **kwargs)
return wrapped
return decorate
# Sounds -----------------------------------------------------------------------------------------
# @todo Normalize volume when playing
async def play_voice_line(
interaction: Union[Interaction, None],
voice_channel: VoiceChannel,
board: str,
sound: str,
) -> None:
"""
Play a voice line in the specified channel.
"""
try:
open(f"{SOUNDDIR}/{board}/{sound}")
except IOError:
print(f"Error: Invalid soundfile {SOUNDDIR}/{board}/{sound}!")
if interaction is not None:
await interaction.response.send_message(
f'Heidi sagt: "{board}/{sound}" kanninich finden bruder',
ephemeral=True
)
return
if interaction is not None:
await interaction.response.send_message(f'Heidi sagt: "{board}/{sound}"', ephemeral=True)
audio_source = discord.FFmpegPCMAudio(
f"{SOUNDDIR}/{board}/{sound}"
) # only works from docker
voice_client = await voice_channel.connect()
voice_client.play(audio_source)
while voice_client.is_playing():
await asyncio.sleep(1)
await voice_client.disconnect()
async def play_voice_line_for_member(
interaction: Union[Interaction, None],
member: Member,
board: str,
sound: str,
) -> None:
"""
Play a voice line in the member's current channel.
"""
# Member needs to be in voice channel to hear audio (Heidi needs to know the channel to join)
if (
member is None
or member.voice is None
or member.voice.channel is None
or not isinstance(member.voice.channel, VoiceChannel)
):
print("User not in (valid) voice channel!")
if interaction is not None:
await interaction.response.send_message("Heidi sagt: Komm in den Channel!", ephemeral=True)
return
voice_channel: VoiceChannel = member.voice.channel
await play_voice_line(interaction, voice_channel, board, sound)