import json
import traceback
import os
+import logging
+log = logging.getLogger(__name__)
+log.setLevel(logging.DEBUG)
+ch = logging.StreamHandler()
+ch.setFormatter(logging.Formatter('|%(levelname)s|%(asctime)s|%(module)s| %(message)s'))
+log.addHandler(ch)
+
from collections import defaultdict, OrderedDict
PERSISTENT_DIR = '/var/lib/grahbot'
def get_voice_id(self, guild):
- print('here is self.data for guild {}'.format(self.data['guild']))
+ log.debug('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_user_guild(self, user):
- print('Get user guild enter for {}'.format(user.id))
+ log.debug('Get user guild enter for {}'.format(user.id))
if str(user.id) in self.data['user']:
- print('Found user, returning..')
+ log.debug('Found user, returning..')
retval = discord.utils.get(self.grahbot.guilds, id=self.data['user'][str(user.id)])
- print(retval)
+ log.debug(retval)
if type(retval) != list:
retval = [retval]
return retval
self.rabbit_config = config
def process_msg(self, msg):
- print('>> {}'.format(msg.body))
+ log.debug('>> {}'.format(msg.body))
async def rabbit_connect(self):
- print('Creating rabbitmq socket')
+ log.debug('Creating rabbitmq socket')
# CREATE SOCKET
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
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')
+ log.info('Connected to rabbitmq')
channel = await connection.open_channel()
- print('Declaring exchange')
+ log.debug('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')
+ log.debug('Declaring queue')
self.queue = await self.channel.declare_queue('horn_listener')
await self.queue.bind(exchange, routing_key=self.rabbit_config['exchange'])
- print('Bound')
+ log.debug('Bound')
await self.queue.consume(self.process_msg, no_ack=True)
- print('Consumed a thing')
+ log.debug('Consumed a thing')
# deliver 10 messages to each user
while (True):
class GrahDiscordBot(discord.Client, HornClient):
AUDIO_FILES = ['mp3', '.ogg']
+ CMD_MARKER = '!'
+ CMD_PREFIX = 'command_'
def process_msg(self, msg):
- print('Received a message!!! {}'.format(msg))
+ log.debug('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']))
obj = msg.body
if 'output_type' in obj and obj['output_type'] == 'discord':
- print('Received a horn for us! {}'.format(msg.body))
+ log.debug('Received a horn for us! {}'.format(msg.body))
asyncio.ensure_future(self.horn(obj, properties=None))
else:
- print('Received a horn not for us: {}'.format(msg.body))
+ log.debug('Received a horn not for us: {}'.format(msg.body))
def __init__(self, config):
self.config = config
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')
+ log.debug('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))
+ log.debug('{} selected'.format(sample_name))
return sample_name
async def horn(self, obj, properties):
try:
- print('Horn! {}'.format(obj))
+ log.info('Horn! {}'.format(obj))
# exclusive access on each horn or not?
if 'exclusive' in obj:
exclusive = obj['exclusive']
sample_name = '{}/{}'.format(self.config['airhorn_directory'], obj['sample_name'])
except:
traceback.print_exc()
- print('Error object was: {}'.format(obj))
+ log.debug('Error object was: {}'.format(obj))
else:
await self.msg_play_filename(sample_name, guild_id=obj['guild'], exclusive=exclusive)
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()])
+ log.debug('Logged in as {} ({})'.format(self.user.name, self.user.id))
+ log.debug([x for x in self.get_all_channels()])
#await self.user.edit(nick='Varimathras')
- print(dir(self))
- print(list(self.guilds))
+ log.debug(dir(self))
+ log.debug(list(self.guilds))
for guild in self.guilds:
- print('Checking for rejoin of {}'.format(guild.__repr__()))
+ log.debug('Checking for rejoin of {}'.format(guild.__repr__()))
if self.state.get_voice_id(guild):
- print('Rejoining prior voice channel')
+ log.debug('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('------')
+ log.debug(self.voice_clients)
+ log.debug('------')
@property
def voice_channels(self):
self.state.get_voice(guild).play(discord.FFmpegPCMAudio(filename))
#self.player.start()
else:
- print('Was asked to play {} but no voice channel'.format(filename))
+ log.debug('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')
+ log.debug('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)))
+ log.debug('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)))
+ log.info('Joined voice channel {} {} (id: {})'.format(guild, vc.name, vc.id))
+ log.debug('Voice now {}'.format(self.state.get_voice(guild)))
- print('Exit join voice')
+ log.debug('Exit join voice')
def get_airhorn_filenames(self):
retval = []
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)))
+ log.debug('Found airhorn files:\n{}'.format('\n'.join(retval)))
return retval
cur_chars += len(yieldval)
if index + 1 < len(filename_list):
if len(filename_list[index+1]) + cur_chars > char_limit:
- print('Yielding {}'.format(yieldval))
+ log.debug('Yielding {}'.format(yieldval))
yield yieldval
yieldval = []
cur_chars = 0
if yieldval:
- print('Final yield {}'.format(yieldval))
+ log.debug('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))
+ log.debug("Exception: {}\t{}".format(channel, exc))
+ exc_string = 'Ruh Roh! {}'.format(str(exc))
traceback.print_exc()
await channel.send(exc_string)
def print_call(self, message):
- print('#{} <{}>: {}'.format(message.channel, message.author, message.content))
+ if isinstance(message.channel, discord.DMChannel):
+ guild_str = ''
+ else:
+ guild_str = str(message.channel.guild)
+ log.info('{}#{} <{}>: {}'.format(guild_str, message.channel, message.author, message.content))
def member_guild_list(self, member):
def contextual_guild(self, message):
channel = message.channel
if isinstance(channel, discord.DMChannel):
- print('Is a DM with {}'.format(channel.recipient))
+ log.debug('Is a DM with {}'.format(channel.recipient))
retval = self.member_guild_list(channel.recipient)
- print('Member guilds: {}'.format(retval))
+ log.debug('Member guilds: {}'.format(retval))
return retval
else:
- print('Guild: {}'.format(channel.guild))
+ log.debug('Guild: {}'.format(channel.guild))
return [channel.guild]
else:
return self.contextual_guild(message)
- def select_guild(self, message):
- print('Selectguild {}'.format(message.content))
+ async def command_selectguild(self, message, guild):
+ log.debug('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))
+ log.debug('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
-
+ async def command_sleep(self, message, guild):
+ await asyncio.sleep(5)
+ await message.channel.send('Done sleeping')
+
+ async def command_join(self, message, guild):
+ log.info('Was instructed to join {} guild {}'.format(message.content.split(' ')[1], str(guild)))
+ await self.msg_join_voice_channel(message.content.split(' ')[1], guild=guild)
+
+ async def command_play(self, message, guild):
+ log.info('Was instructed to play {}'.format(message.content.split(' ')[1]))
+ await self.msg_play_sound(name=' '.join(message.content.split(' ')[1:]), guild=guild)
+
+ async def command_list(self, message, guild):
+ log.info('Asked for list')
+ for airhorn_files in self.chunk_it_up(self.get_airhorn_filenames()):
+ log.debug('Sending {}'.format(airhorn_files))
+ await message.channel.send('```\n{}```'.format('\n'.join(airhorn_files)))
+
+ async def command_leave(self, message, guild):
+ await self.state.get_voice(guild).disconnect()
+ self.state.set_voice(guild, None)
+
+ async def command_help(self, message, guild):
+ await message.channel.send('```\n!join [channel]\n!play [file]\n!list (for all of them)\n!leave```')
+
+
+ async def command_whoami(self, message, guild):
+ await message.channel.send('```{}```'.format(self.debug_info()))
def debug_info(self):
return socket.gethostname()
+
+ def get_command_names(self):
+ cmds = [self.CMD_SYMBOL+x.replace('command_', '') for x in dir(self) if x.startswith('command_')]
+
+ def get_command_func(self, command_name):
+ command_func_names = [x for x in dir(self) if x.startswith(self.CMD_PREFIX)]
+ log.debug('searching for command with name {}'.format(command_name))
+ log.debug('command func names {}'.format(command_func_names))
+ search_func_name = '{}{}'.format(self.CMD_PREFIX, command_name)
+ if search_func_name in command_func_names:
+ search_func = getattr(self, search_func_name)
+ return search_func
+ raise GrahDiscordException('Did not find {} in commands'.format(command_name))
+
+ async def handle_command(self, message):
+ self.print_call(message)
+ log.debug('gettin guilds here')
+ guilds = self.channel_guild(message)
+ log.debug(guilds)
+ potential_command = message.content[1:].split(' ')[0]
+
+ if potential_command == 'selectguild':
+ func = self.get_command_func(potential_command)
+ await func(message, guild=None)
+ 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]
+
+ func = self.get_command_func(potential_command)
+ await func(message, guild)
+
+
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()))
+ if message.content.startswith(self.CMD_MARKER):
+ await self.handle_command(message)
except Exception as e:
await self.oh_no(message.channel, e)