--- /dev/null
+#!/usr/bin/python3
+
+import discord
+import socket
+import random
+import ssl
+import asynqp
+import discord.voice_client
+import datetime
+import asyncio
+import json
+import traceback
+import os
+from collections import defaultdict, OrderedDict
+
+PERSISTENT_DIR = '/var/lib/grahbot'
+
+
+class GrahState(object):
+ FILENAME = '{}/state.json'.format(PERSISTENT_DIR)
+ def __init__(self, grahbot, filename=FILENAME):
+ self.filename = filename
+ self.voice = defaultdict(lambda: None)
+ self.grahbot = grahbot
+ self.load()
+
+ def load(self):
+ if os.path.exists(self.filename):
+ self.data = json.load(open(self.filename, 'r'))
+ else:
+ self.data = OrderedDict()
+ if 'user' not in self.data:
+ self.data['user'] = {}
+ if 'guild' not in self.data:
+ self.data['guild'] = {}
+ self.save()
+
+ def save(self):
+ json.dump(self.data, open(self.filename, 'w'))
+
+
+ def set_voice(self, guild, voice):
+ self.set_voice_by_id(guild.id, voice)
+
+ def set_voice_by_id(self, guild_id, voice):
+ self.data['guild'][str(guild_id)] = voice.channel.id
+ if not self.voice[str(guild_id)]:
+ self.voice[str(guild_id)] = voice
+ self.save()
+
+
+ def get_voice_id(self, guild):
+ print('here is self.data for guild {}'.format(self.data['guild']))
+ if str(guild.id) in self.data['guild']:
+ return discord.utils.get(self.grahbot.voice_channels, id=self.data['guild'][str(guild.id)])
+ else:
+ return None
+
+ def get_voice(self, guild):
+ return self.get_voice_by_id(guild.id)
+
+ def get_voice_by_id(self, guild_id):
+ if str(guild_id) in self.voice:
+ return self.voice[str(guild_id)]
+ else:
+ return None
+
+ def get_user_guild(self, user):
+ print('Get user guild enter for {}'.format(user.id))
+ if str(user.id) in self.data['user']:
+ print('Found user, returning..')
+ retval = discord.utils.get(self.grahbot.guilds, id=self.data['user'][str(user.id)])
+ print(retval)
+ if type(retval) != list:
+ retval = [retval]
+ return retval
+ else:
+ return None
+
+ def set_user_guild(self, user, guild):
+ self.data['user'][str(user.id)] = guild.id
+ self.save()
+
+class HornClient(object):
+ def __init__(self, config):
+ self.rabbit_config = config
+
+ def process_msg(self, msg):
+ print('>> {}'.format(msg.body))
+
+ async def rabbit_connect(self):
+ print('Creating rabbitmq socket')
+ # CREATE SOCKET
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ # WRAP SOCKET
+ sock = ssl.wrap_socket(sock)
+ sock.connect((self.rabbit_config['host'], int(self.rabbit_config['port'])))
+
+ connection = await asynqp.connect(virtual_host=self.rabbit_config['vhost'], username=self.rabbit_config['user'], password=self.rabbit_config['password'], sock=sock)
+ print('Connected to rabbitmq')
+ channel = await connection.open_channel()
+ print('Declaring exchange')
+ exchange = await channel.declare_exchange(self.rabbit_config['exchange'], 'topic', passive=True)
+
+ # we have 10 users. Set up a queue for each of them
+ # use different channels to avoid any interference
+ # during message consumption, just in case.
+ self.channel = await connection.open_channel()
+ print('Declaring queue')
+ self.queue = await self.channel.declare_queue('horn_listener')
+ await self.queue.bind(exchange, routing_key=self.rabbit_config['exchange'])
+ print('Bound')
+ await self.queue.consume(self.process_msg, no_ack=True)
+ print('Consumed a thing')
+
+ # deliver 10 messages to each user
+ while (True):
+ await asyncio.sleep(1)
+ #msg = asynqp.Message("omg here is the time {}".format(datetime.datetime.now()))
+ #exchange.publish(msg, routing_key=self.rabbit_config['exchange'])
+
+
+class GrahDiscordException(Exception):
+ pass
+
+
+
+class GrahDiscordBot(discord.Client, HornClient):
+ AUDIO_FILES = ['mp3', '.ogg']
+ def process_msg(self, msg):
+ print('Received a message!!! {}'.format(msg))
+ if msg._properties['content_type'] == 'application/json':
+ # decode the object from json
+ obj = json.loads(msg.body.decode(msg._properties['content_encoding']))
+ else:
+ obj = msg.body
+
+ if 'output_type' in obj and obj['output_type'] == 'discord':
+ print('Received a horn for us! {}'.format(msg.body))
+ asyncio.ensure_future(self.horn(dict(sample_name=obj['sample_name']), properties=None))
+ else:
+ print('Received a horn not for us: {}'.format(msg.body))
+
+ def __init__(self, config):
+ self.config = config
+ self.player = None
+ self.used = []
+ self.state = GrahState(grahbot=self)
+
+ self.loop = asyncio.get_event_loop()
+ #self.horn_client = HornClient('config-piege.json')
+ HornClient.__init__(self, config)
+ self.rabbit = self.loop.create_task(self.rabbit_connect())
+ discord.Client.__init__(self, loop=self.loop)
+ self.loop_forever()
+
+ def terminate_all(self, guild):
+ if self.state.get_voice(guild):
+ if self.state.get_voice(guild).is_playing():
+ self.state.get_voice(guild).stop()
+
+ def get_sample_name(self):
+ selections = os.listdir(self.config['airhorn_directory'])
+ 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:
+ self.used.pop(use)
+ while len(self.used) < len(selections) and sample_name in self.used:
+ print('already used, researching')
+ sample_name = random.choice(selections)
+ self.used.append(sample_name)
+ if len(self.used) == len(selections):
+ self.used = []
+ sample_name = "{}/{}".format(self.config['airhorn_directory'], sample_name)
+ print('{} selected'.format(sample_name))
+ return sample_name
+
+ async def horn(self, obj, properties):
+ try:
+ print('Horn! {}'.format(obj))
+ # exclusive access on each horn or not?
+ if 'exclusive' in obj:
+ exclusive = obj['exclusive']
+ else:
+ exclusive = False
+
+ if obj['sample_name'] == 'random':
+ sample_name = self.get_sample_name()
+ elif obj['sample_name'] == 'terminate':
+ self.terminate_all()
+ return None
+ else:
+ sample_name = '{}/{}'.format(self.config['airhorn_directory'], obj['sample_name'])
+ except:
+ traceback.print_exc()
+ print('Error object was: {}'.format(obj))
+ else:
+ await self.msg_play_filename(sample_name, guild_id=336396117791211522, exclusive=exclusive)
+
+
+
+
+ # for further manipulation if we want to do funky stuff
+ def loop_forever(self):
+ try:
+ self.loop.run_until_complete(self.start(self.config['token']))
+ except KeyboardInterrupt:
+ self.loop.run_until_complete(self.logout())
+ pending = asyncio.all_tasks(loop=self.loop)
+ gathered = asyncio.gather(*pending, loop=self.loop)
+ try:
+ gathered.cancel()
+ self.loop.run_until_complete(gathered)
+
+ # we want to retrieve any exceptions to make sure that
+ # they don't nag us about it being un-retrieved.
+ gathered.exception()
+ except:
+ pass
+ except Exception:
+ pass
+ finally:
+ self.loop.close()
+
+ 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()])
+ #await self.user.edit(nick='Varimathras')
+ print(dir(self))
+ print(list(self.guilds))
+ for guild in self.guilds:
+ print('Checking for rejoin of {}'.format(guild.__repr__()))
+ if self.state.get_voice_id(guild):
+ print('Rejoining prior voice channel')
+ await self.msg_join_voice_channel(self.state.get_voice_id(guild).name, guild)
+ self.member_guilds = {}
+ print(self.voice_clients)
+ print('------')
+
+ @property
+ def voice_channels(self):
+ return [x for x in self.get_all_channels() if x.type == discord.ChannelType.voice]
+
+
+ @property
+ 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
+
+ async def msg_play_sound(self, name=None, guild=None):
+ if name:
+ 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_id=guild.id)
+
+ async def msg_play_filename(self, filename, guild_id, exclusive=False):
+ guild = discord.utils.get(self.guilds, id=guild_id)
+ if self.state.get_voice(guild):
+ self.terminate_all(guild=guild)
+ self.state.get_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, guild):
+ print('Called join voice channel')
+ for vc in self.voice_channels:
+ 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.state.get_voice(guild):
+ if vc != self.state.get_voice(guild).channel:
+ self.state.set_voice(guild, await self.state.get_voice(guild).move_to(vc))
+ else:
+ self.state.set_voice(guild, await vc.connect())
+ print('Joined voice channel {} {} (id: {})'.format(guild, vc.name, vc.id))
+ print('Voice now {}'.format(self.state.get_voice(guild)))
+
+ print('Exit join voice')
+
+ def get_airhorn_filenames(self):
+ retval = []
+ for x in os.listdir(self.config['airhorn_directory']):
+ if self.is_audio_file(x):
+ retval.append(x.lower())
+ retval = sorted([x[:-4] for x in retval])
+ print('Found airhorn files:\n{}'.format('\n'.join(retval)))
+ return retval
+
+
+ def chunk_it_up(self, filename_list):
+ yieldval = []
+ char_limit = 1950
+ cur_chars = 0
+ for index, filename in enumerate(filename_list):
+ yieldval.append(filename)
+ cur_chars += len(yieldval)
+ if index + 1 < len(filename_list):
+ if len(filename_list[index+1]) + cur_chars > char_limit:
+ print('Yielding {}'.format(yieldval))
+ yield yieldval
+ yieldval = []
+ cur_chars = 0
+
+ if yieldval:
+ print('Final yield {}'.format(yieldval))
+ yield yieldval
+
+
+ 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 channel.send(exc_string)
+
+ def print_call(self, message):
+ print('#{} <{}>: {}'.format(message.channel, message.author, message.content))
+
+
+ def member_guild_list(self, member):
+ return [x for x in self.guilds if member in x.members]
+
+ def contextual_guild(self, message):
+ channel = message.channel
+ if isinstance(channel, discord.DMChannel):
+ print('Is a DM with {}'.format(channel.recipient))
+ retval = self.member_guild_list(channel.recipient)
+ print('Member guilds: {}'.format(retval))
+ return retval
+ else:
+ print('Guild: {}'.format(channel.guild))
+ return [channel.guild]
+
+
+ def channel_guild(self, message):
+ if isinstance(message.channel, discord.DMChannel):
+ return self.state.get_user_guild(message.channel.recipient)
+ else:
+ return self.contextual_guild(message)
+
+ def select_guild(self, message):
+ print('Selectguild {}'.format(message.content))
+ guilds = self.contextual_guild(message)
+ if len(guilds) < 2:
+ raise Exception('No, this is not needed')
+ guild_name = message.content.replace('!selectguild ', '')
+ for guild in guilds:
+ if guild.name == guild_name:
+ print('Setting member {} to guild {}'.format(message.channel.recipient, guild.name))
+ self.member_guilds[message.channel.recipient] = [guild]
+ self.state.set_user_guild(message.channel.recipient, guild)
+ break
+
+
+
+ def debug_info(self):
+ return socket.gethostname()
+
+ async def on_message(self, message):
+ try:
+ if message.author != self.user:
+ print('gettin guilds here')
+ guilds = self.channel_guild(message)
+ print(guilds)
+ if message.content.startswith('!selectguild'):
+ self.select_guild(message)
+ return
+
+ 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('!join'):
+ 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()):
+ print('Sending {}'.format(airhorn_files))
+ await message.channel.send('```\n{}```'.format('\n'.join(airhorn_files)))
+ elif message.content == '!leave':
+ await self.state.get_voice(guild).disconnect()
+ self.state.set_voice(guild, None)
+ elif message.content.startswith('!selectguild'):
+ self.print_call(message)
+ await self.select_guild(message)
+ elif message.content == '!help':
+ self.print_call(message)
+ await message.channel.send('```\n!join [channel]\n!play [file]\n!list (for all of them)\n!leave```')
+ elif message.content == '!whoami':
+ self.print_call(message)
+ await message.channel.send('```{}```'.format(self.debug_info()))
+ except Exception as e:
+ await self.oh_no(message.channel, e)
+
+if __name__ == '__main__':
+ config = json.load(open('{}/config.json'.format(PERSISTENT_DIR), 'r'))
+ bot = GrahDiscordBot(config)
+++ /dev/null
-#!/usr/bin/python3
-
-import sys
-import discord
-import socket
-import random
-import ssl
-import asynqp
-import discord.voice_client
-import datetime
-import asyncio
-import json
-import traceback
-import os
-
-class HornClient(object):
- def __init__(self, config):
- self.rabbit_config = config
-
- def process_msg(self, msg):
- print('>> {}'.format(msg.body))
-
- @asyncio.coroutine
- async def rabbit_connect(self):
- # CREATE SOCKET
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-
- # WRAP SOCKET
- sock = ssl.wrap_socket(sock)
- sock.connect((self.rabbit_config['host'], int(self.rabbit_config['port'])))
-
- connection = await asynqp.connect(virtual_host=self.rabbit_config['vhost'], username=self.rabbit_config['user'], password=self.rabbit_config['password'], sock=sock)
- channel = await connection.open_channel()
- exchange = await channel.declare_exchange(self.rabbit_config['exchange'], 'topic', passive=True)
-
- # we have 10 users. Set up a queue for each of them
- # use different channels to avoid any interference
- # during message consumption, just in case.
- self.channel = await connection.open_channel()
- self.queue = await self.channel.declare_queue('horn_listener')
- await self.queue.bind(exchange, routing_key=self.rabbit_config['exchange'])
- await self.queue.consume(self.process_msg, no_ack=True)
-
- # deliver 10 messages to each user
- while (True):
- await asyncio.sleep(1)
- #msg = asynqp.Message("omg here is the time {}".format(datetime.datetime.now()))
- #exchange.publish(msg, routing_key=self.rabbit_config['exchange'])
-
-
-class GrahDiscordException(Exception):
- pass
-
-
-
-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
- obj = json.loads(msg.body.decode(msg._properties['content_encoding']))
- else:
- obj = msg.body
-
- if 'output_type' in obj and obj['output_type'] == 'discord':
- print('Received a horn for us! {}'.format(msg.body))
- asyncio.async(self.horn(dict(sample_name=obj['sample_name']), properties=None))
- else:
- print('Received a horn not for us: {}'.format(msg.body))
-
- def __init__(self, config):
- self.config = config
- self.voice = {}
- self.player = None
- self.used = []
-
- self.loop = asyncio.get_event_loop()
- #self.horn_client = HornClient('config-piege.json')
- HornClient.__init__(self, config)
- discord.Client.__init__(self, loop=self.loop)
- asyncio.async(self.rabbit_connect())
- self.loop_forever()
-
- 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 self.is_audio_file(x)]
- sample_name = random.choice(selections)
- for index, use in enumerate(self.used):
- if use not in selections:
- self.used.pop(use)
- while len(self.used) < len(selections) and sample_name in self.used:
- print('already used, researching')
- sample_name = random.choice(selections)
- self.used.append(sample_name)
- if len(self.used) == len(selections):
- self.used = []
- sample_name = "{}/{}".format(self.config['airhorn_directory'], sample_name)
- print('{} selected'.format(sample_name))
- return sample_name
-
- @asyncio.coroutine
- async def horn(self, obj, properties):
- try:
- print('Horn! {}'.format(obj))
- # exclusive access on each horn or not?
- if 'exclusive' in obj:
- exclusive = obj['exclusive']
- else:
- exclusive = False
-
- if obj['sample_name'] == 'random':
- sample_name = self.get_sample_name()
- elif obj['sample_name'] == 'terminate':
- self.terminate_all()
- return None
- else:
- sample_name = '{}/{}'.format(self.config['airhorn_directory'], obj['sample_name'])
- except:
- traceback.print_exc()
- print('Error object was: {}'.format(obj))
- else:
- await self.msg_play_filename(sample_name, exclusive=exclusive)
-
-
-
-
- # for further manipulation if we want to do funky stuff
- def loop_forever(self):
- try:
- self.loop.run_until_complete(self.start(self.config['token']))
- except KeyboardInterrupt:
- self.loop.run_until_complete(self.logout())
- pending = asyncio.Task.all_tasks(loop=self.loop)
- gathered = asyncio.gather(*pending, loop=self.loop)
- try:
- gathered.cancel()
- self.loop.run_until_complete(gathered)
-
- # we want to retrieve any exceptions to make sure that
- # they don't nag us about it being un-retrieved.
- gathered.exception()
- except:
- pass
- finally:
- self.loop.close()
-
- @asyncio.coroutine
- 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(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
- def voice_channels(self):
- return [x for x in self.get_all_channels() if x.type == discord.ChannelType.voice]
-
-
- @property
- 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, guild=None):
- if name:
- 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, 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, guild):
- print('Called join voice channel')
- for vc in self.voice_channels:
- 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[guild]:
- if vc != self.voice[guild].channel:
- await self.voice[guild].move_to(vc)
- else:
- 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):
- 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):
- yieldval = []
- char_limit = 1950
- cur_chars = 0
- for index, filename in enumerate(filename_list):
- yieldval.append(filename)
- cur_chars += len(yieldval)
- if index + 1 < len(filename_list):
- if len(filename_list[index+1]) + cur_chars > char_limit:
- yield yieldval
- yieldval = []
- cur_chars = 0
-
- if yieldval:
- yield yieldval
-
-
- @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 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.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 = GrahDiscordBot(config)