async def duelingtheme(self, ctx, *args): """Get Dueling Questions from a particular theme! ~duelingtheme""" logging_utils.log_command("duelingtheme", ctx.channel, ctx.author) themes = self.quarter_tab_get_column("A") user_theme = " ".join(args) # No supplied theme -- give themes if len(args) < 1 or user_theme not in themes: embed = discord_utils.create_embed() embed.add_field(name="Available Themes", value="\n".join(themes)) await ctx.send(embed=embed) return question = self.quarter_tab_get_question(user_theme, 1) embed = discord_utils.create_embed() embed.add_field( name=dueling_constants.THEME, value=question[0], ) #inline=False) embed.add_field( name=dueling_constants.CATEGORY, value=question[1], ) #inline=False) embed.add_field(name=dueling_constants.QUESTION, value=question[2], inline=False) embed.add_field(name=dueling_constants.ANSWER, value=dueling_utils.format_spoiler_answer(question[3]), inline=False) await ctx.send(embed=embed)
async def endrace(self, ctx): """ DONT USE PLS Ends the race Usage: ~endrace """ logging_utils.log_command("endrace", ctx.channel, ctx.author) channel = ctx.channel.id if channel not in self.current_races: embed = discord_utils.create_embed() embed.add_field( name="No race!", value= "This channel doesn't have a race going on. You can't end something that hasn't started!", inline=False) embed.add_field( name="Start Race", value=f"To start a race, use {ctx.prefix}startrace", inline=False) await ctx.send(embed=embed) return self.current_races.pop(channel) embed = discord_utils.create_embed() embed.add_field( name="Race Stopped", value=f"To start a new race, use {ctx.prefix}startrace", inline=False) embed.add_field( name="Experimental", value= "ehm, this command is still in development. It actually probably didn't do anything, sorry!", inline=False) await ctx.send(embed=embed)
def create_code_embed(level: int, codes: pd.DataFrame, prefix: str): """ Function to create the cipher_race embed :param level: (int) The level of the current puzzle solvers :param codes: (pandas.DataFrame) the current set of codes :param prefix: (str) The bot prefix for the server the message came from :return embeds: (list of discord.Embed) The embeds we create for the cipher_race :return code_answer: (list of str) the answers to the given codes """ code_answers = [] embed_list = [] embed = discord_utils.create_embed() embed.add_field(name=f"Level {level}", value=f"Welcome to level {level}! You will have {compute_level_time(level)} " + \ f"seconds to solve {level} {cipher_race_constants.CODE}s, beginning now.", inline=False) embed_list.append(embed) for i in range(level): code_proposal = codes.sample() embed_list.append(discord_utils.create_embed()) embed_list[-1].add_field( name=f"{cipher_race_constants.CODE.capitalize()} #{i + 1}", value=f"{code_proposal[cipher_race_constants.URL].item()}", inline=False) embed_list[-1].set_image( url=code_proposal[cipher_race_constants.URL].item()) code_answers.append( code_proposal[cipher_race_constants.ANSWER].item().replace( ' ', '').lower()) embed_list.append(discord_utils.create_embed()) embed_list[-1].add_field( name="Answering", value= f"Use {prefix}answer to make a guess on any of the {cipher_race_constants.CODE}s.", inline=False) return embed_list, code_answers
async def on_error(event, *args, **kwargs): """When an exception is raised, log it in err.log and bot log channel""" print(f"Printing from on_error: {args[0]}") _, error, _ = sys.exc_info() embed = discord_utils.create_embed() # error while handling message if event in [ "message", "on_message", "message_discarded", "on_message_discarded", "on_command_error", ]: msg = f"**Error while handling a message**" user_error = ErrorHandler(args[0], error, msg).handle_error() if user_error: embed.add_field(name="Error!", value=user_error, inline=False) # other errors else: msg = f"An error occurred during an event and was not reported: {event}" user_error = ErrorHandler(args[0], error, msg).handle_error()# TODO: change args[0] to "" if user_error: embed = discord_utils.create_embed() embed.add_field(name="Error!", value=user_error, inline=False) await args[0].channel.send(embed=embed)
async def duelingcategory(self, ctx, *args): """Get Dueling Questions from a particular category! ~duelingcat""" logging_utils.log_command("duelingcategory", ctx.channel, ctx.author) categories = self.quarter_tab_get_column("B") user_cat = " ".join(args) # No supplied category -- give cats if len(args) < 1 or user_cat not in categories: embed = discord_utils.create_embed() embed.add_field(name="Available Categories", value="\n".join(categories)) await ctx.send(embed=embed) return # Find all questions of the given category # TODO: Hardcoded question = self.quarter_tab_get_question(user_cat, 2) embed = discord_utils.create_embed() embed.add_field( name=dueling_constants.THEME, value=question[0], ) #inline=False) embed.add_field( name=dueling_constants.CATEGORY, value=question[1], ) #inline=False) embed.add_field(name=dueling_constants.QUESTION, value=question[2], inline=False) embed.add_field(name=dueling_constants.ANSWER, value=dueling_utils.format_spoiler_answer(question[3]), inline=False) await ctx.send(embed=embed)
async def archiveserver(self, ctx): """Command to archive every text channel in the server. WARNING: This command will take *very* long on any reasonably aged server Usage: `!archiveserver`""" logging_utils.log_command("archiveserver", ctx.channel, ctx.author) # If we don't have the lock, let the user know it may take a while. msg = None if self.lock.locked(): msg = await ctx.send(embed=archive_utils.get_delay_embed()) # LOCK EVERYTHING async with self.lock: start_embed = await self.get_start_embed(ctx.guild, ctx.guild.text_channels) if msg: await msg.delete() msg = None # SOMETIMES THE EMBED IS TOO LONG FOR DISCORD embeds = discord_utils.split_embed(start_embed) msgs = [] for embed in embeds: msgs.append(await ctx.send(embed=embed)) for text_channel in ctx.guild.text_channels: archive_utils.reset_archive_dir() try: zip_file, zip_file_size, textfile, textfile_size = await self.archive_one_channel( text_channel) file, embed = self.get_file_and_embed( text_channel, ctx.guild.filesize_limit, zip_file, zip_file_size, textfile, textfile_size) await ctx.send(file=file, embed=embed) except nextcord.errors.Forbidden: embed = discord_utils.create_embed() embed.add_field( name="ERROR: No access", value= f"Sorry! I don't have access to {text_channel.mention}. You'll need " f"to give me permission to view the channel if you want " f"to archive it", inline=False) await ctx.send(embed=embed) continue if msgs: for msg in msgs: await msg.delete() embed = discord_utils.create_embed() embed.add_field(name="All Done!", value=f"Successfully archived {ctx.guild}", inline=False) await ctx.send(embed=embed) # Clean up the archive dir archive_utils.reset_archive_dir()
async def reload(self, ctx): """ Admin Command. Reload the Google Sheet so we can update our codes instantly. Usage: ~reload """ logging_utils.log_command("reload", ctx.channel, ctx.author) self.sheet_map = { cipher_race_constants.HP: google_utils.get_dataframe_from_gsheet( self.spreadsheet.worksheet( cipher_race_constants.HP_SHEET_TAB_NAME), cipher_race_constants.COLUMNS), cipher_race_constants.COMMON: google_utils.get_dataframe_from_gsheet( self.spreadsheet.worksheet( cipher_race_constants.COMMON_SHEET_TAB_NAME), cipher_race_constants.COLUMNS), cipher_race_constants.CHALLENGE: google_utils.get_dataframe_from_gsheet( self.spreadsheet.worksheet( cipher_race_constants.CHALLENGE_SHEET_TAB_NAME), cipher_race_constants.COLUMNS) } embed = discord_utils.create_embed() embed.add_field(name="Sheet Reloaded", value="Google sheet successfully reloaded", inline=False) await ctx.send(embed=embed)
async def countdown(self, ctx, *args): """Uses discord message time formatting to provide a countdown Usage: `~countdown September 22, 2021 9:00pm EDT` """ logging_utils.log_command("countdown", ctx.channel, ctx.author) if len(args) < 1: embed = discord_utils.create_no_argument_embed("time") await ctx.send(embed=embed) return user_time = time_utils.parse_date(" ".join(args)) if user_time is None: embed = discord_utils.create_embed() embed.add_field(name=f"Failed!", value=f"Is {' '.join(args)} a valid time?", inline=False) await ctx.send(embed=embed) return unix_time = int(datetime.timestamp(user_time)) embed = discord.Embed(title=f"{' '.join(args)}", description=f"<t:{unix_time}:f>\n" f"`<t:{unix_time}:R>` - <t:{unix_time}:R>\n\n" f"[Guide to format](https://discord.com/developers/docs/reference#message-formatting-formats)", color=constants.EMBED_COLOR) await ctx.send(embed=embed)
async def deleteactivity(self, ctx, *args): """Remove all instances of activity from the calendar ~deleteactivity Dueling""" logging_utils.log_command("deleteactivity", ctx.channel, ctx.author) # In general, I've been adding activities with specifics e.g. "Dueling: Helga Game" # If you want to delete only that instance, ~dactivity "Dueling: Helga Game" # If you want to delete all dueling activities, ~dactivity Dueling activity = ' '.join(args) result_cells = self.activity_calendar_sheet.findall( ctx.guild.name, in_column=activity_calendar_constants.SHEET_SERVER_COLUMN) num_deletions = 0 # TODO: I think this whole num_deletions thing becomes a non-issue if we just sort the rows # in a descending order for cell in result_cells: row = self.activity_calendar_sheet.row_values(cell.row) if activity in row[ activity_calendar_constants.SHEET_ACTIVITY_COLUMN - 1]: self.activity_calendar_sheet.delete_row(cell.row - num_deletions) num_deletions += 1 embed = discord_utils.create_embed() embed.add_field( name="Success", value= f"Deleted {num_deletions} instances of {activity} from the calendar.", inline=False) await ctx.send(embed=embed)
async def time(self, ctx, *args): """Return the time in the specified location ~time Amsterdam""" logging_utils.log_command("time", ctx.channel, ctx.author) # No location provided if len(args) < 1: embed = discord_utils.create_no_argument_embed("location") await ctx.send(embed=embed) return # Allow long input (e.g. St. Louis, Missouri, USA) location = " ".join(args) timezone_dict = self.get_tz(location) # Unable to find the location in the geonames database if timezone_dict is None: embed = discord_utils.create_embed() embed.add_field(name="Error!", value=f"Cannot find {location}!", inline=False) await ctx.send(embed=embed) return names = ["Location (Timezone)", "Current Time"] # The DB provides a - (GMT) for west timezones but not a + for the east values = [f"{location.title()} ({time_utils.format_gmt_offset(timezone_dict)})", time_utils.format_time(timezone_dict['time'])] embed = discord_utils.populate_embed(names, values, inline=False) await ctx.send(embed=embed)
async def search(self, ctx, *args): """ Command to search the interwebs! (google) Usage: ~search <target_site> <[query...]> """ logging_utils.log_command("search", ctx.channel, ctx.author) if len(args) < 2: await ctx.send(embed=discord_utils.create_no_argument_embed( "Target Site and Query")) return target_site = args[0].lower() if target_site in lookup_constants.REGISTERED_SITES: target_site = lookup_constants.REGISTERED_SITES[target_site] # If we do a google search, we want to return the 10 top results # Otherwise, we want to just send the most relevant result if target_site == lookup_constants.GOOGLE: is_google_search = True else: is_google_search = False original_query = ' '.join(args[1:]) # Don't add google to the query but add any other target site for easier access/SEO if not is_google_search: query = original_query + ' ' + target_site else: query = original_query # Dude this loop is going to be horrible wtf # If google: # Store all results as a list and print them out line by line in an embed # If not google: # Find the first result that matches the target site and return that # If we can't find it, return the google query I think embed = discord_utils.create_embed() results = [] for result in googlesearch.search(query, num=lookup_constants.QUERY_NUM, stop=lookup_constants.QUERY_NUM, pause=lookup_constants.PAUSE_TIME): if target_site in result: embed.add_field( name= f"{target_site.capitalize()} Result for {original_query}", value=result) await ctx.send(embed=embed) return results.append(result) if is_google_search: embed.add_field( name=f"{target_site.capitalize()} Result for {original_query}", value=f"{chr(10).join(results)}") else: embed.add_field( name=f"Search failed!", value= f"Sorry! We weren't able to find a {target_site.capitalize()}" f"link for {original_query}. However, here are the top 10 hits on Google:\n" f"{chr(10).join(results)}") await ctx.send(embed=embed)
def get_delay_embed(): embed = discord_utils.create_embed() embed.add_field( name="Warning: Delay!", value= "Hi! It appears we're a little busy at the moment, so our archiving may take a while. " "Sorry about that! We'll get to it as soon as possible.", inline=False) return embed
async def real_help(self, ctx, *args): if len(args) < 1: embed = discord.Embed( title=f"{help_constants.HELP}", url="https://github.com/kevslinger/DiscordCipherRace", color=constants.EMBED_COLOR) embed.add_field( name="Welcome!", value= f"Welcome to the help page! We offer the following modules. " f"Use {constants.BOT_PREFIX}oldhelp <module> to learn about " f"the commands in that module!", inline=False) embed.add_field( name=help_constants.CIPHER_RACE, value=f"Race against the clock as you decode ciphers. " f"Use {constants.BOT_PREFIX}startrace " "to start a race! " f"\nRead more on the [GitHub README]({help_constants.CIPHER_RACE_README})", inline=False) embed.add_field( name=help_constants.HOUSE_POINTS, value=f"Get the house points standings! " f"Use {constants.BOT_PREFIX}housepoints to get the " f"current house points tallies." f"\nRead more on the [GitHub README]({help_constants.HOUSE_POINTS_README})", inline=False) embed.add_field( name=help_constants.LOOKUP, value=f"Search the interwebs (google)!\n" f"Read more on the [GitHub README]({help_constants.LOOKUP_README})", inline=False) embed.add_field( name=help_constants.QUIBBLER, value=f"Get general info about our quarterly magazine!\n" f"Read more on the [GitHub README]({help_constants.QUIBBLER_README})", inline=False) embed.add_field( name=help_constants.TIME, value=f"Current time anywhere in the world!\n" f"Read more on the [GitHub README]({help_constants.TIME_README})", inline=False) else: module = ' '.join(args).lower() if module in MODULE_TO_HELP: embed = MODULE_TO_HELP[module]() else: embed = discord_utils.create_embed() embed.add_field( name="Module not found!", value= f"Sorry! Cannot find module {module}. The modules we have are \n" f"{', '.join(help_constants.MODULES)}", inline=False) await ctx.send(embed=embed)
async def remindme(self, ctx, *args): """ Reminds you to do something later. Pick one of days (d), hours (h), minutes (m) Usage: `~remindme 24h Take out the trash` """ logging_utils.log_command("remindme", ctx.channel, ctx.author) utctime = datetime.datetime.now(tz=pytz.UTC) # TODO: I'm being REALLY loose on the arguments here if 'd' in args[0]: remind_time = utctime + datetime.timedelta(days=int(args[0][:-1])) elif 'h' in args[0]: remind_time = utctime + datetime.timedelta(hours=int(args[0][:-1])) elif 'm' in args[0]: remind_time = utctime + datetime.timedelta( minutes=int(args[0][:-1])) else: embed = discord_utils.create_embed() embed.add_field( name=f"{constants.FAILED}!", value="Must supply a unit of time! (e.g. 5d, 24h, 30m)", inline=False) await ctx.send(embed=embed) return self.reminder_tab.append_row([ ctx.guild.name, ctx.channel.name, str(ctx.channel.id), remind_time.strftime(constants.SHEET_DATETIME_FORMAT), ctx.author.name, str(ctx.author.id), ' '.join(args[1:]) ]) embed = discord_utils.create_embed() embed.add_field( name=f"{constants.SUCCESS}!", value= f"I will remind you to {' '.join(args[1:])} <t:{int(datetime.datetime.timestamp(remind_time))}:R>", inline=False) await ctx.send(embed=embed)
async def google(self, ctx, *args): """Gets the top 10 google results for your query ~google The Leaning Tower of Piza""" logging_utils.log_command("google", ctx.channel, ctx.author) results = lookup_utils.search_query(' '.join(args)) embed = discord_utils.create_embed() embed.add_field(name=f"Google Result for {' '.join(args)}", value=f"{chr(10).join(results)}") await ctx.send(embed=embed)
async def on_command_error(ctx, error): """When a command exception is raised, log it in err.log and bot log channel""" details = f"**Error while running command**\n'''\n{ctx.message.clean_content}\n'''" user_error = ErrorHandler(ctx.message, error, details).handle_error() if user_error: embed = discord_utils.create_embed() embed.add_field(name="Error!", value=user_error, inline=False) await ctx.send(embed=embed) else: print("on_command_error has no user_error")
async def duelingmultiplechoice(self, ctx): """Get A Multiple Choice Question ~duelingmc""" logging_utils.log_command("duelingmultiplechoice", ctx.channel, ctx.author) embed = discord_utils.create_embed() # Cut off header quarter_questions = self.quarter_tab.get_all_values()[1:] question = quarter_questions[np.random.randint(len(quarter_questions))] # TODO: Hacky way of saying there are not multiple options i = 0 while question[-1] == "": question = quarter_questions[np.random.randint( len(quarter_questions))] i += 1 if i >= 100: embed.add_field( name=f"{constants.FAILED}!", value= f"Sorry! I was unable to find a multiple choice question. Try again later?" ) await ctx.send(embed=embed) return multiple_choice = [question[3]] + question[5:] np.random.shuffle(multiple_choice) embed.add_field( name=dueling_constants.THEME, value=question[0], ) #inline=False) embed.add_field( name=dueling_constants.CATEGORY, value=question[1], ) #inline=False) embed.add_field(name=dueling_constants.QUESTION, value=question[2], inline=False) embed.add_field( name=dueling_constants.CHOICES, # TODO: woof that hardcoded formatting # Some of the answers are ints value="\n".join([ f"{letter}.) {str(answer)}" for letter, answer in zip( string.ascii_uppercase, multiple_choice) ])) embed.add_field(name=dueling_constants.ANSWER, value=dueling_utils.format_spoiler_answer(question[3], filler=20), inline=False) await ctx.send(embed=embed)
def create_no_code_embed(prefix: str) -> discord.Embed: """ Function to create an embed to say there is no cipher_race :param prefix: (str) the prefix for the server :return embed: (discord.Embed) The embed we create """ embed = discord_utils.create_embed() embed.add_field( name=f"No Current {cipher_race_constants.CODE.capitalize()}", value= f"You haven't started the race. To start, use the {prefix}startrace command.", inline=False) return embed
async def monthlychecklist(self, ctx): """ Prints out a list of things to do at the start of every month Usage: `~monthlychecklist` """ logging_utils.log_command("monthlychecklist", ctx.channel, ctx.author) checklist = self.get_checklist() embed = discord_utils.create_embed() embed.add_field(name="Monthly Checklist", value=checklist, inline=False) await ctx.send(embed=embed)
def create_level_prep_embed(level: int) -> discord.Embed: """ Create an embed to let the team know their next level will start soon. :param level: (int) the level the team just completed. :param teamname: (str) the name of the team :return embed: (discord.Embed) the embed that includes the level-up message. """ embed = discord_utils.create_embed() embed.add_field( name=f"Level {level} Complete!", value= f"Well done! Level {level+1} will begin in {cipher_race_constants.BREAK_TIME} seconds." ) return embed
async def reset(self, ctx): """ Admin Command. Reset the bot as if it has just loaded up Usage: ~reset Note: Does not reload google sheet. Use ~reload for that """ logging_utils.log_command("reset", ctx.channel, ctx.author) self.current_races = {} embed = discord_utils.create_embed() embed.add_field( name="Success", value= "Bot has been reset, and all races have been forcibly ended. I feel brand new!", inline=False) await ctx.send(embed=embed)
async def post_checklist(self): """Post the monthly checklist to mod chat at Noon UTC on the first of every month.""" utctime = datetime.now(tz=pytz.UTC) # F**k it I'm shooting for noon UTC on the first of the month if utctime.day == 1 and utctime.hour == 12: print("Posting monthly checklist to mod-chat") checklist = self.get_checklist() embed = discord_utils.create_embed() embed.add_field( name= f"Welcome to {utctime.strftime('%B')}! Here's your monthly checklist", value=checklist, inline=False) # Get ravenclaw mod chat mod_chat_channel = self.bot.get_channel(518227474191220777) await mod_chat_channel.send(embed=embed)
def get_opening_statement(sheet_used) -> discord.Embed: """ Assemble the opening message to send to the team before their puzzle begins :return embed: (discord.Embed) the embed that includes the welcome message """ embed = discord_utils.create_embed() embed.add_field( name=f"Welcome!", value= f"You have started a new race against the {sheet_used.capitalize()} wordlist! " f"Level 1 will start in about {cipher_race_constants.BREAK_TIME} seconds from this message! " f"You will have {cipher_race_constants.TIME_LIMIT} seconds to complete levels 1-5. " f"After every {cipher_race_constants.NUM_LEVELS}th level, you will get {cipher_race_constants.BONUS_TIME} " f"additional seconds (i.e you get {cipher_race_constants.TIME_LIMIT + cipher_race_constants.BONUS_TIME} " f"seconds to complete levels 6-10). Good luck and have fun!") return embed
async def duelingrandom(self, ctx): """Give a random question ~duelingrandom""" logging_utils.log_command("duelingrandom", ctx.channel, ctx.author) # Cut off headers possible_questions = self.quarter_tab.get_all_values( )[1:] + self.quotes_tab.get_all_values()[1:] question = possible_questions[np.random.randint( len(possible_questions))] embed = discord_utils.create_embed() # TODO: hardcoded hacked if len(question) <= 5: # name the quote embed.add_field(name=dueling_constants.QUOTE_PROMPT, value=question[0], inline=False) embed.add_field(name=dueling_constants.ANSWER, value=dueling_utils.format_spoiler_answer( question[4]), inline=False) embed.add_field(name="HINT (Book)", value=dueling_utils.format_spoiler_answer( question[2], filler=10), inline=False) else: # MC question (do not give MC) embed.add_field( name=dueling_constants.THEME, value=question[0], ) # inline=False) embed.add_field( name=dueling_constants.CATEGORY, value=question[1], ) # inline=False) embed.add_field(name=dueling_constants.QUESTION, value=question[2], inline=False) embed.add_field(name=dueling_constants.ANSWER, value=dueling_utils.format_spoiler_answer( question[3]), inline=False) await ctx.send(embed=embed)
async def wikipedia(self, ctx, *args): """Gets the Wikipedia article most closely related to your search ~wiki Philadelphia""" logging_utils.log_command("wikipedia", ctx.channel, ctx.author) results = lookup_utils.search_query(' '.join(args), target_site=lookup_constants.WIKI) embed = discord_utils.create_embed() if len(results) > 1: embed.add_field( name=f"Search failed!", value=f"Sorry! We weren't able to find a Wikipedia" f"link for {' '.join(args)}. However, here are the top 10 hits on Google:\n" f"{chr(10).join(results)}") else: embed.add_field(name=f"Wikipedia Result for {' '.join(args)}", value=f"{chr(10).join(results)}") await ctx.send(embed=embed)
async def duelingquote(self, ctx): """Get a quote and answer the SPEAKER and BOOK ~duelingquote""" logging_utils.log_command("duelingquote", ctx.channel, ctx.author) # Cut off header quote_questions = self.quotes_tab.get_all_values()[1:] question = quote_questions[np.random.randint(len(quote_questions))] embed = discord_utils.create_embed() embed.add_field(name=dueling_constants.QUOTE_PROMPT, value=question[0], inline=False) embed.add_field(name=dueling_constants.ANSWER, value=dueling_utils.format_spoiler_answer(question[4]), inline=False) embed.add_field(name="HINT (Book)", value=dueling_utils.format_spoiler_answer(question[2], filler=10), inline=False) await ctx.send(embed=embed)
async def get_start_embed(self, channel_or_guild, multiple_channels=None): embed = discord_utils.create_embed() embed.add_field( name="Archive Started", value= f"Your archiving of {channel_or_guild.mention if hasattr(channel_or_guild, 'mention') else channel_or_guild}" f" has begun! This may take a while. If I run into " f"any errors, I'll let you know.", inline=False) if multiple_channels: embed.add_field( name="List of Channels to Archive", value= f"{chr(10).join([channel.name for channel in multiple_channels])}", inline=False) embed.add_field( name="Problems?", value=f"Taking too long? Let <@!310618854734954497> know", inline=False) return embed
async def startrace(self, ctx, sheet: str = cipher_race_constants.HP): """ Start your race! You will have 60 seconds per level to solve the codes Usage: ~startrace <optional sheet> where sheet is {hp, challenge, common} """ logging_utils.log_command("startrace", ctx.channel, ctx.author) channel = ctx.channel.id if channel in self.current_races: print("startrace called from a channel that's already racing!!") embed = discord_utils.create_embed() embed.add_field( name="Already Racing!", value= f"Stop trying to start a new race while you have one going!", inline=False) await ctx.send(embed=embed) return # Create entry in current_races self.current_races[channel] = dict() self.current_races[channel][cipher_race_constants.LEVEL] = 1 # ~startrace challenge gives you 1000 random english word sheet # ~startrace hp gives you the harry potter sheet # ~startrace common gives you 1000 very common english words if sheet not in self.sheet_map: sheet = cipher_race_constants.HP self.current_races[channel][ cipher_race_constants.CODE] = self.sheet_map[sheet] embeds, self.current_races[channel][ cipher_race_constants. ANSWERS] = cipher_race_utils.create_code_embed( self.current_races[channel][cipher_race_constants.LEVEL], self.current_races[channel][cipher_race_constants.CODE], ctx.prefix) await ctx.send(embed=cipher_race_utils.get_opening_statement(sheet)) # In a short time, send the codes time = Timer(cipher_race_constants.BREAK_TIME, self.start_new_level, callback_args=(ctx, channel, embeds), callback_async=True)
async def unixtime(self, ctx, *args): """Return the time given (or current time if no argument) in Unix format (1626206635) Usage: `~unixtime Tuesday, September 27, 2021 9pm EDT""" logging_utils.log_command("time", ctx.channel, ctx.author) embed = discord_utils.create_embed() if len(args) < 1: curr_time = int(datetime.timestamp(datetime.now())) embed.add_field(name="Success!", value=f"Current time is `{curr_time}`", inline=False) else: user_time = time_utils.parse_date(" ".join(args)) if user_time is None: embed.add_field(name=f"{constants.FAILED}!", value=f"Is {' '.join(args)} a valid time?", inline=False) await ctx.send(embed=embed) return unix_time = int(datetime.timestamp(user_time)) embed.add_field(name=f"{constants.SUCCESS}!", value=f"The Unix Time at {' '.join(args)} is `{unix_time}`", inline=False) await ctx.send(embed=embed)
def get_file_and_embed(self, channel, filesize_limit, zip_file, zip_file_size, textfile, textfile_size): """Check if zipfile and textfile can be sent or not, create embed with message""" embed = discord_utils.create_embed() if zip_file_size > filesize_limit: if textfile_size > filesize_limit: embed.add_field( name="ERROR: History Too Big", value= f"Sorry about that! The chat log in {channel.mention} is too big for me to send.\n" f"The max file size I can send in this server is " f"`{(filesize_limit/self.BYTES_TO_MEGABYTES):.2f}MB`, but the chat log is " f"`{(textfile_size/self.BYTES_TO_MEGABYTES):.2f}MB`", inline=False) file = None else: embed.add_field( name="WARNING: Attachments Too Big", value= f"There are too many photos in {channel.mention} for me to send. The max file size " f"I can send in this server is " f"`{(filesize_limit/self.BYTES_TO_MEGABYTES):.2f}MB` but the zip is " f"`{(zip_file_size/self.BYTES_TO_MEGABYTES):.2f}MB`. I'll only be able to send you the chat log.", inline=False) ZIP_FILENAME = os.path.join(archive_constants.ARCHIVE, channel.name + '_archive.zip') with zipfile.ZipFile(ZIP_FILENAME, mode='w') as zf: zf.write(os.path.join( archive_constants.ARCHIVE, channel.name + '_' + archive_constants.TEXT_LOG_PATH), compress_type=self.compression) file = zip_file else: file = zip_file embed = None return file, embed