All checks were successful
Build Heidi Docker image / build-docker (push) Successful in 14s
/instantbuttons displays a soundboard via a button ui
106 lines
3.1 KiB
Python
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)
|