From 5ebf5820fbc7ea0675f81424d43bb65d4e9a7e98 Mon Sep 17 00:00:00 2001 From: jweigele Date: Sun, 6 Sep 2020 23:03:16 -0700 Subject: [PATCH] Some iteration on the API changes, and an attempt to shard by "guild" which is the new server --- wigglydiscord.py | 162 +++++++++++++++++++++++++++++++---------------- 1 file changed, 109 insertions(+), 53 deletions(-) diff --git a/wigglydiscord.py b/wigglydiscord.py index 40e2850..ca8977b 100755 --- a/wigglydiscord.py +++ b/wigglydiscord.py @@ -13,8 +13,6 @@ import json import traceback import os -SOUND_DIR="soundboard/" - class HornClient(object): def __init__(self, config): self.rabbit_config = config @@ -50,12 +48,13 @@ class HornClient(object): #exchange.publish(msg, routing_key=self.rabbit_config['exchange']) -class WigglyDiscordException(Exception): +class GrahDiscordException(Exception): pass -class WigglyDiscordBot(discord.Client, HornClient): +class GrahDiscordBot(discord.Client, HornClient): + AUDIO_FILES = ['mp3', '.ogg'] def process_msg(self, msg): if msg._properties['content_type'] == 'application/json': # decode the object from json @@ -71,7 +70,7 @@ class WigglyDiscordBot(discord.Client, HornClient): def __init__(self, config): self.config = config - self.voice = None + self.voice = {} self.player = None self.used = [] @@ -82,15 +81,14 @@ class WigglyDiscordBot(discord.Client, HornClient): asyncio.async(self.rabbit_connect()) self.loop_forever() - def terminate_all(self): - if self.voice: - if self.player: - if self.player.is_playing(): - self.player.stop() + def terminate_all(self, guild): + if self.voice[guild]: + if self.voice[guild].is_playing(): + self.voice[guild].stop() def get_sample_name(self): selections = os.listdir(self.config['airhorn_directory']) - selections = [x for x in selections if '.mp3' in x] + selections = [x for x in selections if self.is_audio_file(x)] sample_name = random.choice(selections) for index, use in enumerate(self.used): if use not in selections: @@ -107,7 +105,6 @@ class WigglyDiscordBot(discord.Client, HornClient): @asyncio.coroutine async def horn(self, obj, properties): - try: print('Horn! {}'.format(obj)) # exclusive access on each horn or not? @@ -156,8 +153,15 @@ class WigglyDiscordBot(discord.Client, HornClient): async def on_ready(self): print('Logged in as {} ({})'.format(self.user.name, self.user.id)) print([x for x in self.get_all_channels()]) - print(list(self.servers)) - print(self.is_voice_connected(list(self.servers)[0])) + print(dir(self)) + print(list(self.guilds)) + for guild in self.guilds: + self.voice[guild] = None + print(self.voice_clients) +# if len(self.voice_clients) > 0: +# print('Found a preexisting voice client: {}'.format(self.voice_clients)) +# self.voice[guild] = self.voice_clients[0] + #print(self.is_voice_connected(list(self.guilds)[0])) print('------') @property @@ -169,41 +173,64 @@ class WigglyDiscordBot(discord.Client, HornClient): def text_channels(self): return [x for x in self.get_all_channels() if x.type == discord.ChannelType.text] + def is_audio_file(self, filename): + fn = filename.lower() + if any([fn.endswith(y) for y in self.AUDIO_FILES]): + return True + else: + return False + + def name_matches_filename(self, name, filename): + name = name.lower() + filename = filename.lower() + if '.'.join(filename.split('.')[:-1]) == name and self.is_audio_file(filename): + return True + else: + return False + @asyncio.coroutine - async def msg_play_sound(self, name=None): + async def msg_play_sound(self, name=None, guild=None): if name: - filename = '{}/{}.mp3'.format(self.config['airhorn_directory'], name) - if not os.path.exists(filename): - raise WigglyDiscordException("File '{}' not found in airhorn directory".format(name)) - await self.msg_play_filename(filename) + filename=None + for fn in os.listdir(self.config['airhorn_directory']): + if self.name_matches_filename(name, fn): + filename = '{}/{}'.format(self.config['airhorn_directory'], fn) + break + if not filename or not os.path.exists(filename): + raise GrahDiscordException("File '{}' not found in airhorn directory".format(name)) + await self.msg_play_filename(filename, guild=guild) @asyncio.coroutine - async def msg_play_filename(self, filename, exclusive=False): - if self.voice: - self.terminate_all() - self.player = self.voice.create_ffmpeg_player(filename) - self.player.start() + async def msg_play_filename(self, filename, exclusive=False, guild=None): + if self.voice[guild]: + self.terminate_all(guild=guild) + self.voice[guild].play(discord.FFmpegPCMAudio(filename)) + #self.player.start() else: print('Was asked to play {} but no voice channel'.format(filename)) - async def msg_join_voice_channel(self, channel_name): + async def msg_join_voice_channel(self, channel_name, guild): print('Called join voice channel') for vc in self.voice_channels: - if vc.name == channel_name: + if vc.name == channel_name and (not guild or vc.guild == guild): print('Found a voice channel to join {} {}'.format(vc, type(vc))) - if self.voice: - if vc != self.voice.channel: - self.voice = await self.voice.move_to(vc) + if self.voice[guild]: + if vc != self.voice[guild].channel: + await self.voice[guild].move_to(vc) else: - self.voice = await self.join_voice_channel(vc) - print('Joined voice channel {} (id: {})'.format(vc.name, vc.id)) - print('Voice now {}'.format(self.voice)) + self.voice[guild] = await vc.connect() + print('Joined voice channel {} {} (id: {})'.format(guild, vc.name, vc.id)) + print('Voice now {}'.format(self.voice[guild])) print('Exit join voice') def get_airhorn_filenames(self): - return sorted([x[:-4] for x in os.listdir(self.config['airhorn_directory']) if 'mp3' in x.lower()]) + retval = [] + for x in os.listdir(self.config['airhorn_directory']): + if self.is_audio_file(x): + retval.append(x.lower()) + return sorted([x[:-4] for x in retval]) def chunk_it_up(self, filename_list): @@ -225,37 +252,66 @@ class WigglyDiscordBot(discord.Client, HornClient): @asyncio.coroutine async def oh_no(self, channel, exc): + print("Exception: {}\t{}".format(channel, exc)) exc_string = 'Ruh Roh! {}: {}'.format(type(exc), str(exc)) traceback.print_exc() - await self.send_message(channel, exc_string) + await channel.send(exc_string) def print_call(self, message): print('#{} <{}>: {}'.format(message.channel, message.author, message.content)) + + def member_guilds(self, member): + return [x for x in self.guilds if member in x.members] + + def contextual_guild(self, message): + channel = message.channel + print(channel) + if isinstance(channel, discord.DMChannel): + print('Is a DM with {}'.format(channel.recipient)) + retval = self.member_guilds(channel.recipient) + print('Member guilds: {}'.format(retval)) + return retval + else: + print('Guild: {}'.format(channel.guild)) + return [channel.guild] + @asyncio.coroutine async def on_message(self, message): try: - if message.content.startswith('!sleep'): - await asyncio.sleep(5) - await self.send_message(message.channel, 'Done sleeping') - elif message.content.startswith('!joinvoice'): - self.print_call(message) - print('Was instructed to join {}'.format(message.content.split(' ')[1])) - await self.msg_join_voice_channel(message.content.split(' ')[1]) - elif message.content.startswith('!play'): - self.print_call(message) - print('Was instructed to play {}'.format(message.content.split(' ')[1])) - await self.msg_play_sound(name=' '.join(message.content.split(' ')[1:])) - elif message.content.startswith('!listairhorns'): - self.print_call(message) - for airhorn_files in self.chunk_it_up(self.get_airhorn_filenames()): - await self.send_message(message.channel, '```{}```'.format('\n'.join(airhorn_files))) - elif message.content.startswith('!leavevoice'): - await self.voice.disconnect() - self.voice = None + if message.author != self.user: + guilds = self.contextual_guild(message) + if len(guilds) == 0: + return + elif len(guilds) >1: + await message.channel.send('Too many guilds!!!\n{}'.format('\n'.join([str(x) for x in guilds]))) + return + elif len(guilds) == 1: + guild = guilds[0] + + if message.content.startswith('!sleep'): + await asyncio.sleep(5) + await message.channel.send('Done sleeping') + elif message.content.startswith('!joinvoice'): + self.print_call(message) + print('Was instructed to join {} guild {}'.format(message.content.split(' ')[1], str(guild))) + await self.msg_join_voice_channel(message.content.split(' ')[1], guild=guild) + elif message.content.startswith('!play'): + self.print_call(message) + print('Was instructed to play {}'.format(message.content.split(' ')[1])) + await self.msg_play_sound(name=' '.join(message.content.split(' ')[1:]), guild=guild) + elif message.content == '!list': + self.print_call(message) + for airhorn_files in self.chunk_it_up(self.get_airhorn_filenames()): + await message.channel.send('```{}```'.format('\n'.join(airhorn_files))) + elif message.content == '!leavevoice': + await self.voice[guild].disconnect() + self.voice[guild] = None + elif message.content == '!help': + await message.channel.send('```!joinvoice [channel]\n!play [file]\n!list (for all of them)\n!leavevoice```') except Exception as e: await self.oh_no(message.channel, e) if __name__ == '__main__': config = json.load(open(sys.argv[1], 'r')) - bot = WigglyDiscordBot(config) + bot = GrahDiscordBot(config) -- 2.30.2