async def process_submission(message): user_id = str(message.author.id) logger.debug(f'Processing submission, msg id {user_id}') if user_id in data.participants: logger.info('Submission invalid') else: try: url = message.attachments[0].proxy_url except IndexError: url = '' loggger.warn('Submission does not have an image attached') data.participants[user_id] = { 'nick': message.author.display_name, 'submitted': True, 'image_url': url, 'voted': False, 'votes': 0 } await message.channel.send(random.choice(static.quotes['rude'])) logger.info('Submission valid') data.save_state()
def load(): global token, server_id, command_prefix, admin_ids, main_channel_id, leaderboard_channel_id, data_root logger.info('Loading config...') try: with open(CONFIG_PATH) as file: try: config = json.load(file) except json.decoder.JSONDecodeError: fatal(f'↳ Cannot parse {CONFIG_PATH}') try: token = config['token'] server_id = config['server_id'] command_prefix = config['command_prefix'] admin_ids = config['admin_ids'] main_channel_id = config['main_channel_id'] leaderboard_channel_id = config['leaderboard_channel_id'] data_root = config['data_root'] if 'data_root' in config.keys() else '.' logger.debug('↳ Config loaded') except KeyError: fatal(f'↳ Cannot find required keys in {CONFIG_PATH}\ \nSee README.md for required structure') except OSError: logger.warn(f'↳ Cannot open {CONFIG_PATH}') env = Env() token = env('TOKEN') server_id = env.int('SERVER_ID') command_prefix = env('COMMAND_PREFIX') admin_ids = list(map(lambda x: int(x), env.list('ADMIN_IDS'))) main_channel_id = env.int('MAIN_CHANNEL_ID') leaderboard_channel_id = env.int('LEADERBOARD_CHANNEL_ID') data_root = env('DATA_ROOT') if 'DATA_ROOT' in os.environ else '.' logger.debug('↳ Config loaded from environment')
async def log_and_dm(title, reason, person): embed = discord.Embed( title=title, description=reason, colour=0xff0000) await person.send(embed=embed) logger.info(reason + ', ' + title)
def load_state(): global participants, voting_map, period, mode logger.debug('Loading state...') try: with open(STATE_PATH, 'r') as file: try: data = json.load(file) except json.decoder.JSONDecodeError: fatal(f'↳ Cannot parse {STATE_PATH}') try: participants = data['participants'] voting_map = data['voting_map'] period = data['period'] mode = data['mode'] logger.info('↳ Using existing state file') except KeyError: fatal(f'↳ Cannot find required keys in {STATE_PATH}') except OSError: participants = {} voting_map = {} period = DEFAULT_PERIOD mode = DEFAULT_MODE logger.info('↳ No existing state file, starting with blank state') save_state()
async def on_message(message): # don't respond to our own messages if message.author.bot: return await bot.process_commands(message) # ignore messages in any channel but the main one if message.channel != main_channel: return now = datetime.datetime.now() hour = int(now.strftime('%H')) minute = int(now.strftime('%M')) if data.period == 'submissions' and len(message.attachments) > 0: logger.info( f'Submission from \'{message.author.display_name}\' ({str(message.author.id)})' ) await submissions.process_submission(message) elif data.period == 'voting' and len(message.clean_content) == 1: logger.info( f'Vote \'{message.clean_content}\' from \'{message.author.display_name}\' ({str(message.author.id)})' ) await voting.check_vote(message)
async def on_ready(): global main_channel, leaderboard_channel logger.debug('Finding text channels...') builtins.main_channel = bot.get_channel(config.main_channel_id) builtins.leaderboard_channel = bot.get_channel(config.leaderboard_channel_id) logger.info('Food Flex is online!')
def main(): logger.info(f'Starting Food Flex v{__version__}') static.load() data.load_state() data.load_leaderboard() print_state_info() logger.info('Starting bot...') bot.loop.create_task(check_time_periods()) bot.run(config.token)
def change_period(new_period, manual_change=False): global period, mode if manual_change: mode = 'manual' else: mode = 'automatic' logger.info(f'Period \'{period}\' -> \'{new_period}\' ({mode})') period = new_period save_state()
def save_leaderboard(): global leaderboard, leaderboard_message_id logger.debug('Saving leaderboard...') try: os.makedirs(DATA_PATH, exist_ok=True) with open(LEADERBOARD_PATH, 'w') as file: json.dump({ 'leaderboard': leaderboard, 'leaderboard_message_id': leaderboard_message_id }, file, indent=2) logger.info('Leaderboard saved') except OSError: fatal(f'↳ Could not save to {STATE_PATH}')
async def submission_period(): logger.info('// Now in SUBMISSIONS period //') activity = discord.Activity( name=static.strings['submission_open_activity'], type=discord.ActivityType.watching) await bot.change_presence(status=discord.Status.online, activity=activity) embed = discord.Embed(title=static.strings['submission_open_title'], description=static.strings['submission_open'], colour=0xff0000) await main_channel.send(embed=embed) logger.debug('Clearing participants & voting_map') data.participants.clear() data.voting_map.clear() data.save_state()
def save_state(): global participants, voting_map, period, mode logger.debug('Saving state...') try: os.makedirs(DATA_PATH, exist_ok=True) with open(STATE_PATH, 'w') as file: json.dump({ 'participants': participants, 'voting_map': voting_map, 'period': period, 'mode': mode }, file, indent=2) logger.info('State saved') except OSError: fatal(f'↳ Could not save to {STATE_PATH}')
def load_leaderboard(): global leaderboard, leaderboard_message_id logger.debug('Loading leaderboard...') try: with open(LEADERBOARD_PATH) as file: try: data = json.load(file) except json.decoder.JSONDecodeError: fatal(f'↳ Cannot parse {LEADERBOARD_PATH}') try: leaderboard = data['leaderboard'] leaderboard_message_id = data['leaderboard_message_id'] logger.info('↳ Using existing leaderboard file') except KeyError: fatal(f'↳ Cannot find required keys in {LEADERBOARD_PATH}') except OSError: leaderboard = {} leaderboard_message_id = None logger.info('↳ No existing leaderboard file, starting with blank') save_leaderboard()
async def results_period(): logger.info('// Now in RESULTS period //') activity = discord.Activity(name='for shit food', type=discord.ActivityType.watching) await bot.change_presence(status=discord.Status.idle, activity=activity) logger.info('Preparing reuslts...') # Get list of users (tuples) who submitted (nick, votes) users = [] for user in data.participants: if data.participants[user]['submitted']: tuple = (data.participants[user]['nick'], data.participants[user]['votes']) users.append(tuple) users.sort(key=lambda tuple: tuple[1], reverse=True) # Get the winner(s) as a string winner_message = await get_winner() embed = discord.Embed(title='Results', description='', colour=0xff0000) embed.set_author(name=winner_message) # Add users to embed for user in users: votes = 'Votes: ' + str(user[1]) embed.add_field(name=user[0], value=votes, inline=False) await main_channel.send(embed=embed) logger.info('Results posted') await leaderboard.update_leaderboard()
def load(): global quotes, strings logger.debug('Loading quotes & strings...') try: with open(QUOTES_PATH) as file: try: quotes = json.load(file) except json.decoder.JSONDecodeError: fatal(f'↳ Cannot parse {QUOTES_PATH}') except OSError: fatal(f'↳ Cannot open {QUOTES_PATH}') try: with open(STRINGS_PATH) as file: try: strings = json.load(file) except json.decoder.JSONDecodeError: fatal(f'↳ Cannot parse {STRINGS_PATH}') except OSError: fatal(f'↳ Cannot open {STRINGS_PATH}') logger.info('↳ Quotes & strings loaded')
def load(): global token, server_id, command_prefix, admin_ids, main_channel_id, leaderboard_channel_id logger.info('Loading config...') try: with open(CONFIG_PATH) as file: try: config = json.load(file) except json.decoder.JSONDecodeError: fatal(f'↳ Cannot parse {CONFIG_PATH}') try: token = config['token'] server_id = config['server_id'] command_prefix = config['command_prefix'] admin_ids = config['admin_ids'] main_channel_id = config['main_channel_id'] leaderboard_channel_id = config['leaderboard_channel_id'] logger.debug('↳ Config loaded') except KeyError: fatal(f'↳ Cannot find required keys in {CONFIG_PATH}\ \nSee README.md for required structure') except OSError: fatal(f'↳ Cannot open {CONFIG_PATH}')
async def voting_period(): logger.info('// Now in VOTING period //') logger.info('Creating voting key...') # we need to build voting_map map first build_voting_map() logger.debug('Creating (url, letter) pairs for submissions...') submissions = [] # create (image_url, letter) pair list for letter in data.voting_map: user_id = data.voting_map[letter] image_url = data.participants[user_id]['image_url'] submissions.append((image_url, letter)) # sort submissions by alphabetical key submissions.sort(key=lambda tuple: tuple[1], reverse=False) logger.debug('Generating images...') # process images image_objects = [] for (image_url, letter) in submissions: buffer = images.process_image(image_url, letter) image_objects.append(discord.File(buffer, filename=f'{letter}.png')) # announce voting is open await main_channel.send(static.strings['voting_open_title']) logger.debug('Uploading images...') # upload images for image in image_objects: await main_channel.send(file=image) # remind people how to vote and change presence await main_channel.send(static.strings['voting_open_footer']) activity = discord.Activity(name='people vote on shit food', type=discord.ActivityType.watching) await bot.change_presence(status=discord.Status.online, activity=activity) logger.info('Done, voting key posted')
def set_mode(new_mode): global mode logger.info(f'Mode \'{mode}\' -> \'{new_mode}\'') mode = new_mode save_state()
def print_state_info(): logger.info( f'period=\'{data.period}\', mode=\'{data.mode}\' people={len(data.participants)}' )