async def MAIN(message, args, level, perms, TWOW_CENTRAL): db = Database() months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ] if level == 1: # If just tc/bd, return info on their birthday found = db.get_entries("birthday", conditions={"id": str(message.author.id)}) if found == []: await message.channel.send( f"""You are yet to register your birthday! You can register by using **{PREFIX}birthday register `DD/MM` `timezone`**""" .replace("\t", "")) return birthday, tz = found[0][1:] birthday = birthday.split("/") birthday_format = months[int(birthday[1]) - 1] + " " + str(birthday[0]) timezone_f = ("+" if tz > 0 else "") + str(tz) await message.channel.send( f"""**{message.author.name}**'s birthday is set as **{birthday_format}** in **UTC {timezone_f}**.""" ) return if args[1].lower() == "view": if level == 2: found = db.get_entries("birthday") found = sorted(found, key=lambda k: int(k[1].split("/")[0])) found = sorted(found, key=lambda k: int(k[1].split("/")[1])) day, month = datetime.now(timezone.utc).day, datetime.now( timezone.utc).month for bd in found: if int(bd[1].split("/")[1]) > month: next_bd = bd break elif int(bd[1].split("/")[1]) == month and int( bd[1].split("/")[0]) > day: next_bd = bd break else: next_bd = found[0] next_id, birthday, tz = next_bd birthday = birthday.split("/") birthday_format = months[int(birthday[1]) - 1] + " " + str( int(birthday[0])) timezone_f = ("+" if tz > 0 else "") + str(tz) try: username = TWOW_CENTRAL.get_member(int(next_id)).name except AttributeError: username = next_id await message.channel.send( f"The next birthday is **{username}**'s, on **{birthday_format}** in **UTC {timezone_f}**." ) return rest = " ".join(args[2:]) if rest.startswith("<@") and rest.endswith(">"): rest = rest[2:-1] if is_whole(rest): found = db.get_entries("birthday", conditions={"id": rest}) try: username = TWOW_CENTRAL.get_member(int(rest)).name except: username = rest if found == []: await message.channel.send( f"**{username}** has not registered a birthday yet!") return user_bd = found[0] birthday, tz = user_bd[1:] birthday = birthday.split("/") birthday_format = months[int(birthday[1]) - 1] + " " + str( int(birthday[0])) timezone_f = ("+" if tz > 0 else "") + str(tz) await message.channel.send( f"**{username}**'s birthday is on **{birthday_format}** in **UTC {timezone_f}**." ) return else: user = discord.utils.get(TWOW_CENTRAL.members, name=rest) if user is None: await message.channel.send("That user is not in the server!") return found = db.get_entries("birthday", conditions={"id": str(user.id)}) if found == []: await message.channel.send( f"**{rest}** has not registered a birthday yet!") return user_bd = found[0] birthday, tz = user_bd[1:] birthday = birthday.split("/") birthday_format = months[int(birthday[1]) - 1] + " " + str( int(birthday[0])) timezone_f = ("+" if tz > 0 else "") + str(tz) await message.channel.send( f"**{rest}**'s birthday is on **{birthday_format}** in **UTC {timezone_f}**." ) return if args[1].lower() == "register": if level == 2: await message.channel.send( "Include your birthday in `DD/MM` to register!") return # Check if the person is in the birthday database or not found = db.get_entries("birthday", conditions={"id": str(message.author.id)}) print(found) birthday = args[2].split("/") if level == 3: tz = 0 elif not is_whole(args[3]): await message.channel.send( "Invalid timezone! Make sure it's a whole number from -12 to 14!" ) return elif not -12 <= int(args[3]) <= 14: await message.channel.send( "Invalid timezone! Make sure it's a whole number from -12 to 14!" ) return else: tz = int(args[3]) if len(birthday) != 2: # If it's not `n/n` await message.channel.send( "Invalid birthday! Make sure it's in the `DD/MM` format!") return if not is_whole(birthday[0]) or not is_whole( birthday[1]): # If day and month aren't numbers await message.channel.send( "Invalid birthday! Make sure the day and month are both numbers!" ) return # Transform into integers for these next two checks birthday[0] = int(birthday[0]) birthday[1] = int(birthday[1]) if not 1 <= birthday[1] <= 12: # If month is invalid await message.channel.send( "Invalid month! Make sure it's between 1 and 12.") return if not 1 <= birthday[0] <= monthrange( 2020, birthday[1])[1]: # monthrange checks days in the month await message.channel.send( # 2020 months because it's a leap year, and 29/02 should be available f"Invalid day! Make sure it's between 1 and {monthrange(2020, birthday[1])[1]} for that month." ) return birthday_format = months[birthday[1] - 1] + " " + str(birthday[0]) birthday = "/".join([str(x) for x in birthday ]) # Join the list again for the next few lines timezone_f = ("+" if tz > 0 else "") + str(tz) # This confirmation message cannot be bypassed await message.channel.send( f"""Are you sure you want to record your birthday as {birthday_format} and your timezone as UTC {timezone_f}? Send `confirm` in this channel to confirm. """.replace("\n", "").replace("\t", "")) # Wait for a message by the same author in the same channel msg = await BRAIN.wait_for( 'message', check=(lambda m: m.channel == message.channel and m.author == message.author)) if msg.content.lower( ) != "confirm": # If it's not `confirm`, cancel command await message.channel.send("Birthday registering cancelled.") return # If confirmation passed, record the birthday if found == []: is_new = "" db.add_entry("birthday", [message.author.id, birthday, tz]) else: is_new = "new " db.edit_entry("birthday", entry={ "birthday": birthday, "timezone": tz }, conditions={"id": str(message.author.id)}) await message.channel.send( f"Successfully recorded your {is_new}birthday as **{birthday} UTC {timezone_f}**!" ) return
async def MAIN(message, args, level, perms, SERVER): if isinstance(message.channel, discord.DMChannel ): # Everyone should be able to see button presses await message.channel.send("This command cannot be used in DMs!") return db = Database() if level == 1: # `tc/button` will check the current button try: # "public.bigredbutton" always has a single entry unless there has never been a button. If len(button_info) # is 0, that's the case, and this will throw an error caught by the try except block. button_info = db.get_entries("bigredbutton", columns=["button", "info"])[0] except IndexError: button_info = db.get_entries("bigredbutton", columns=["button", "info"]) if len(button_info) == 0: # If there is no button, create one button_number = 1 # It'd be the first ever button serial_number = key_generator(random.randrange( 8, 15)) # Generate serial exploding_chance = random.randrange( 15, 51) # 15 to 50% chance of exploding inspector = number_key(3) # Factory inspector code db.add_entry( "bigredbutton", [1, f"{serial_number} {exploding_chance} {inspector}", "", ""]) # Insert the new button info. Now there is a button, so skip to [*] elif button_info[ 1] == "PRESSED": # This is the 3 second interval after a button is pressed and before return # the outcome is announced. Ignore button checks for this period elif len(button_info[1].split(" ")) == 1: # [#] # Button, when in cooldown, has a single code for its info column, representing when it was pressed and # if it blew up or not. This code, unlike the normal `serial exp_chance` information, has no space in # it. This section detects that code pressing_time = int( button_info[1][2:]) # Time at which the button was pressed if button_info[1].startswith( "0-"): # `0-time` means button didn't blow up left = int((pressing_time + 15) - time.time()) # Time left for button to come back if left < 0: # If it's negative, the button should've returned by now but didn't # So generate the button on the spot button_number = button_info[ 0] + 1 # Increment button number serial_number = key_generator(random.randrange( 8, 15)) # Generate serial exploding_chance = random.randrange( 15, 51) # 15 to 50% chance of exploding inspector = number_key(3) # Factory inspector code n_info = f"{serial_number} {exploding_chance} {inspector}" db.edit_entry("bigredbutton", entry={ "button": button_number, "info": n_info }) # Update with the new button else: # If it's not negative, and the timer hasn't ended, report the amount of time remaining await message.channel.send( f"The new button is currently being prepared! {left}s remain!" ) return if button_info[1].startswith( "1-"): # `1-time` means the button blew up left = int((pressing_time + 300) - time.time()) # Time left for button to come back if left < 0: # Read above about the timer being negative button_number = button_info[0] + 1 serial_number = key_generator(random.randrange(8, 15)) exploding_chance = random.randrange(15, 51) inspector = number_key(3) n_info = f"{serial_number} {exploding_chance} {inspector}" db.edit_entry("bigredbutton", entry={ "button": button_number, "info": n_info }) # Update with new button else: # Report the actual timer if it hasn't ended yet mn = int(left / 60) # Extract minutes sc = left % 60 # Extract seconds await message.channel.send( f"The new button is being reconstructed. {mn}min {sc}s remain!" ) return else: # If there's a button and that's it button_number = button_info[0] # Report the button number... serial_number = button_info[1].split(" ")[0] # Its serial... exploding_chance = button_info[1].split(" ")[ 1] # ...Its explosion chance inspector = button_info[1].split(" ")[2] # And its inspector # [*] Report the current button await message.channel.send( f"""<:bigredbutton:654042578617892893> This is **Big Red Button #{button_number}** It has a **{exploding_chance}%** chance of exploding. The serial number is `{serial_number}`. It was inspected and approved by Factory Inspector #{inspector}. Use `tc/bigredbutton press` to press this button!""".replace("\t", "")) return if args[1].lower() == "top": # Points leaderboard unformatted_points = db.get_entries("bigredbutton", columns=["points"])[0] unformatted_points = [ x.split("-") for x in unformatted_points[0].split(" ") ] # unformatted_points might include empty strings from how the points value is formatted points = [] # This variable will be the clean version for x in unformatted_points: try: x[0] = int(x[0]) x[1] = int(x[1]) points.append( x) # If it passed the int tests, append it to points except ValueError: # If it fails to convert to integers, it's an empty string and is ignored continue points = sorted(points, reverse=True, key=lambda x: x[1]) # Sort the leaderboard player_info = [x for x in points if x[0] == message.author.id][0] player_ind = points.index(player_info) # args[2] is the page number. if level == 2: # If it's not specified, assume it's the first page points = points[:10] page = 1 elif not is_whole( args[2] ): # If it's not a valid integer, assume it's first page also points = points[:10] page = 1 elif (int(args[2]) - 1) * 10 >= len(points): # Detect if the page number is too big await message.channel.send( f"There is no page {args[2]} on Big Red Button!") return else: # This means the user specified a valid page number lower = (int(args[2]) - 1) * 10 upper = int(args[2]) * 10 points = points[lower:upper] page = int(args[2]) # Top of the message beginning = f"```diff\n---⭐ Big Red Button Points Leaderboard Page {page} ⭐---\n" beginning += "\n Rank | Name | Points\n" for person in points: r = points.index(person) + 1 + (page - 1) * 10 if r == 1: # + if the person is first line = f"+ {r}{' ' * (4 - len(str(r)))}| " else: # - otherwise line = f"- {r}{' ' * (4 - len(str(r)))}| " try: # Try to gather a username from the ID member = SERVER["MAIN"].get_member(int(person[0])).name except: # If you can't, just display the ID member = str(person[0]) line += f"{member[:20]}{' ' * (22 - len(member[:20]))}| " # Trim usernames to 20 characters long line += str(person[1]) + "\n" # Add points value and newline beginning += line # Add this line to the final message beginning += f"\nYour rank is {player_ind+1}, with {player_info[1]} points." beginning += "```" # Close off code block await message.channel.send(beginning) return if args[1].lower() == "press": # Press the button! button_info = db.get_entries("bigredbutton")[0] # This segment is almost an exact repeat of [#] up above if len(button_info[1].split(" ")) == 1 and button_info[1] != "PRESSED": pressing_time = int(button_info[1][2:]) if button_info[1].startswith("0-"): left = int((pressing_time + 15) - time.time()) if left < 0: button_number = button_info[0] + 1 serial_number = key_generator(random.randrange(8, 15)) exploding_chance = random.randrange(15, 51) inspector = number_key(3) n_info = f"{serial_number} {exploding_chance} {inspector}" db.edit_entry("bigredbutton", entry={ "button": button_number, "info": n_info }) await message.channel.send( f"""Big Red Button #{button_number} has arrived from inspection by Factory Inspector #{inspector}, now with a {exploding_chance}% chance to explode and a serial number of `{serial_number}`!""".replace("\n", "").replace("\t", "")) return else: await message.channel.send( f"The new button is currently being prepared! {left}s remain!" ) return if button_info[1].startswith("1-"): left = int((pressing_time + 300) - time.time()) if left < 0: button_number = button_info[0] + 1 serial_number = key_generator(random.randrange(8, 15)) exploding_chance = random.randrange(15, 51) inspector = number_key(3) n_info = f"{serial_number} {exploding_chance} {inspector}" db.edit_entry("bigredbutton", entry={ "button": button_number, "info": n_info }) await message.channel.send( f"""Big Red Button #{button_number} has arrived from inspection by Factory Inspector #{inspector}, now with a {exploding_chance}% chance to explode and a serial number of `{serial_number}`!""".replace("\n", "").replace("\t", "")) return else: mn = int(left / 60) sc = left % 60 await message.channel.send( f"The new button is being reconstructed. {mn}min {sc}s remain!" ) return # We already checked button_info[1], check two others now button_number = button_info[0] incapacitated = button_info[2] if str(message.author.id) in incapacitated: # If you're incapacitated incapacitated = incapacitated.split(" ") ind = 0 # Find the author in the incapacitated list and extract their explosion time for incap in incapacitated: if incap.split("-")[0] == str(message.author.id): ind = incapacitated.index(incap) explosion_t = int(incap.split("-")[1]) break # Calculate how long it'll be before they can recover delta = (explosion_t + 21600) - time.time() if delta < 0: # If it's negative, then they already recovered and can go on del incapacitated[ind] # Delete the entry for this person incapacitated = " ".join(incapacitated) # Join the list # Update with the new incapacitated list db.edit_entry("bigredbutton", entry={"incapacitated": incapacitated}) else: # If it's not negative, they still have to wait a little abs_delta = [ int(delta), # Seconds int(delta / 60), # Minutes int(delta / (60 * 60)) ] # Hours sc = abs_delta[0] % 60 mn = abs_delta[1] % 60 hr = abs_delta[2] await message.channel.send( f"You are still incapacitated! Wait {hr}h {mn}min {sc}s to press again." ) return if strip_alpha(message.author.name) == "": return # Don't try to cheese it by having no letters if button_info[ 1] == "PRESSED": # If it's currently being pressed, ignore this press return else: # Mark this button as being pressed so nobody else presses it during the 3 second interval db.edit_entry("bigredbutton", entry={"info": "PRESSED"}) # Gather serial_number and exploding_chance for calculations serial_number = button_info[1].split(" ")[0] exploding_chance = int(button_info[1].split(" ")[1]) inspector = list(button_info[1].split(" ")[2]) new_chance = exploding_chance # Clean slate variable if str(message.author.id)[-1] in serial_number: new_chance *= 0.67 # If last digit of ID is in serial... if strip_alpha(message.author.name)[0].upper() in serial_number: new_chance *= 2 # If first letter of username is in serial... point_retention = 0.5 share_count = 0 disc = list(str(message.author.discriminator)) for x in range(len(list(inspector))): if inspector[x] in disc: share_count += 1 disc.remove(inspector[x]) inspector[x] = "-" if share_count == 2: point_retention = 0.75 if share_count == 3: point_retention = 0.9 seed = random.uniform( 0, 100) # Has to be above the explosion chance otherwise it explodes await message.channel.send( f"**{message.author.name}** presses the button, and...") await asyncio.sleep(3) # Suspense! if seed <= new_chance: # If it's under the explosion chance, it blows up n_button_info = f"1-{int(time.time())}" # Remember, `1-time` is the explosion flag new_inc = f" {message.author.id}-{n_button_info[2:]}" # Add this person to the incapacitated list points = button_info[3].split(" ") # Get the points list new_points = 0 ind = -1 # Find the player in the points list and halve their point count for player in points: if player.split("-")[0] == str(message.author.id): ind = points.index(player) new_points = int( int(player.split("-")[1]) * point_retention) points[ind] = f"{message.author.id}-{new_points}" if ind == -1: # If ind is still -1, then the player wasn't found in the points list so create a new points.append(f"{message.author.id}-{new_points}" ) # entry for them with 0 points points = " ".join(points) db.edit_entry("bigredbutton", entry={ "info": n_button_info, "points": points, "incapacitated": incapacitated + new_inc }) # Update with the explosion info, the new incapacitated list, and the new points list await message.channel.send( f"""<:bigredbutton:654042578617892893> ***The #{button_number} Big Red Button blew up!*** <@{message.author.id}> has been incapacitated. Their point total is now **{new_points}**. They cannot press any more buttons for 6 hours. The button is broken. It'll take **5 minutes** to rebuild it.""".replace( "\t", "")) await asyncio.sleep(300) # Five minutes until the button is back else: # If seed > new_chance, it doesn't blow up points = button_info[3].split(" ") # Get points list to add points n_button_info = f"0-{int(time.time())}" # `0-time` means no explosion ind = -1 # Find player in points list and add the new points for player in points: if player.split("-")[0] == str(message.author.id): ind = points.index(player) # Note: the points they gain is ALWAYS the nominal value for the exploding chance, not the # modified serial number chance that was used to calculate explosions new_points = int(player.split("-")[1]) + exploding_chance points[ind] = f"{message.author.id}-{new_points}" if ind == -1: # If they're not in the points list, add them with the new point value points.append(f"{message.author.id}-{exploding_chance}") points = " ".join(points) db.edit_entry("bigredbutton", entry={ "info": n_button_info, "points": points }) # Update with the pressing info and the new points list await message.channel.send(f""" <:bigredbutton:654042578617892893> The #{button_number} Big Red Button did nothing. <@{message.author.id}> gained {exploding_chance} points. Another button arrives in **15 seconds**. """.replace("\t", "")) await asyncio.sleep(15) # Fifteen seconds until the button is back # Generate new serial_number and exploding_chance button_number += 1 serial_number = key_generator(random.randrange(8, 15)) exploding_chance = random.randrange(15, 51) inspector = number_key(3) n_info = f"{serial_number} {exploding_chance} {inspector}" db.edit_entry("bigredbutton", entry={ "button": button_number, "info": n_info }) # Update table with the new button # Announce the new button await message.channel.send( f"""Big Red Button #{button_number} has arrived from inspection by Factory Inspector #{inspector}, now with a {exploding_chance}% chance to explode and a serial number of `{serial_number}`!""".replace("\n", "").replace("\t", "")) return
async def MAIN(message, args, level, perms, SERVER): if level == 1: await message.channel.send("Include a subcommand!") return VARIABLES = {} db = Database() if args[1].lower() == "info": tag_list = db.get_entries("b++programs", columns=["name", "program", "author", "uses"]) tag_list = sorted(tag_list, reverse=True, key=lambda m: m[3]) tag_leaderboard = False if level == 2: # If it's not specified, assume it's the first page tag_list = tag_list[:10] page = 1 tag_leaderboard = True elif is_whole(args[2]): if (int(args[2]) - 1) * 10 >= len(tag_list): # Detect if the page number is too big await message.channel.send(f"There is no page {args[2]} on the B++ program list!") return else: # This means the user specified a valid page number lower = (int(args[2]) - 1) * 10 upper = int(args[2]) * 10 tag_list = tag_list[lower:upper] page = int(args[2]) tag_leaderboard = True if tag_leaderboard: beginning = f"```diff\nOld B++ Programs Page {page}\n\n" for program in tag_list: r = tag_list.index(program) + 1 + (page - 1) * 10 line = f"{r}{' '*(2-len(str(r)))}: {program[0]} :: {program[3]} use{'s' if program[3] != 1 else ''}" member_id = program[2] try: # Try to gather a username from the ID member = SERVER["MAIN"].get_member(int(member_id)).name except: # If you can't, just display the ID member = str(member_id) line += f" (written by {member})\n" beginning += line # Add this line to the final message beginning += "```" # Close off code block await message.channel.send(beginning) return tag_name = args[2] if tag_name not in [x[0] for x in tag_list]: await message.channel.send("That tag does not exist.") return program = tag_list[[x[0] for x in tag_list].index(tag_name)] member_id = program[2] try: # Try to gather a username from the ID member = SERVER["MAIN"].get_member(int(member_id)).name except: # If you can't, just display the ID member = str(member_id) if len(program[1]) + 6 >= 1900: program_code_msg = program[1] if len(program_code_msg) >= 1990: await message.channel.send(f"**{program[0]}** (written by {member})") await message.channel.send(f"```{program_code_msg[:1000]}```") await message.channel.send(f"```{program_code_msg[1000:]}```") await message.channel.send(f"Used {program[3]} time{'s' if program[3] != 1 else ''}") else: await message.channel.send(f"**{program[0]}** (written by {member})") await message.channel.send(f"```{program_code_msg}```") await message.channel.send(f"Used {program[3]} time{'s' if program[3] != 1 else ''}") else: await message.channel.send(f"""**{program[0]}** (written by {member}) ```{program[1]}``` Used {program[3]} time{'s' if program[3] != 1 else ''}""".replace("\n", "").replace("\t", "")) return if args[1].lower() == "delete": if level == 2: await message.channel.send("Include the name of the program you want to delete!") return tag_name = args[2] tag_list = db.get_entries("b++programs", columns=["name", "author"]) if tag_name in [x[0] for x in tag_list]: ind = [x[0] for x in tag_list].index(tag_name) if tag_list[ind][1] != str(message.author.id) and perms != 2: await message.channel.send(f"You can only delete a program you created!") return db.remove_entry("b++programs", conditions={"name": tag_name}) await message.channel.send(f"Succesfully deleted program {tag_name}!") else: await message.channel.send(f"There's no program under the name `{tag_name}`!") return if args[1].lower() == "edit": if level == 2: await message.channel.send("Include the name of the program you want to edit!") return if level == 3: await message.channel.send("Include the new code for the program you want to edit!") return tag_name = args[2] program = " ".join(args[3:]) if program.startswith("```") and program.endswith("```"): program = program[3:-3] if program.startswith("``") and program.endswith("``"): program = program[2:-2] if program.startswith("`") and program.endswith("`"): program = program[1:-1] tag_list = db.get_entries("b++programs", columns=["name", "author"]) if tag_name in [x[0] for x in tag_list]: ind = [x[0] for x in tag_list].index(tag_name) if tag_list[ind][1] != str(message.author.id) and perms != 2: await message.channel.send(f"You can only edit a program you created!") return db.edit_entry("b++programs", entry={"program": program}, conditions={"name": tag_name}) await message.channel.send(f"Succesfully edited program {tag_name}!") else: await message.channel.send(f"There's no program under the name `{tag_name}`!") return if args[1].lower() not in ["run", "create"]: tag_name = args[1] if (tag_name,) in db.get_entries("b++programs", columns=["name"]): program, uses = db.get_entries( "b++programs", columns=["program", "uses"], conditions={"name": tag_name})[0] uses += 1 db.edit_entry("b++programs", entry={"uses": uses}, conditions={"name": tag_name}) else: await message.channel.send(f"There's no tag under the name `{args[1]}`!") return else: if args[1].lower() == "run": if level == 2: await message.channel.send("Include a program to run!") return program = " ".join(args[2:]) if args[1].lower() == "create": if level == 2: await message.channel.send("Include the name of your new program!") return if level == 3: await message.channel.send("Include the code for your program!") return tag_name = args[2] if len(tag_name) > 30: await message.channel.send("That tag name is too long. 30 characters maximum.") return program = " ".join(args[3:]) if program.startswith("```") and program.endswith("```"): program = program[3:-3] if program.startswith("``") and program.endswith("``"): program = program[2:-2] if program.startswith("`") and program.endswith("`"): program = program[1:-1] if args[1].lower() == "create": if (tag_name,) in db.get_entries("b++programs", columns=["name"]): await message.channel.send("There's already a program with that name!") return db.add_entry("b++programs", [tag_name, program, message.author.id, 0]) await message.channel.send(f"Successfully created program `{tag_name}`!") return semicolon_inds = find_all(program, ";") semicolon_inds = [x for x in semicolon_inds if program[x-1] != "\\"] program_chars = list(program) for ind in semicolon_inds: program_chars[ind] = "\n" program = ''.join(program_chars).replace("\t", "") lines = program.split("\n") context = [] OUTPUT = "" try: try: tag_vars = db.get_entries("b++variables", columns=["name", "value"], conditions={"tag": tag_name}) for var in tag_vars: value = var[1] if value.startswith("[") and value.endswith("]"): value = array_to_list(value) VARIABLES[var[0]] = value except: pass for line in lines: c_line = line if len(context) == 0: declaration = " = " in c_line array_context = "[" in c_line.replace("\[", "") and "]" not in c_line.replace("\]", "") if array_context: context.append(["array", c_line, c_line[c_line.find("["):]]) continue else: context_list = [x[0] for x in context] if "array" in context_list: this_context = context[context_list.index("array")] this_context[1] += "\t" + c_line if "]" not in line.replace("\]", ""): this_context[2] += "\t" + c_line continue else: this_context[2] += c_line[:c_line.find("]")+1] c_line = this_context[1] del context[context_list.index("array")] declaration = " = " in c_line if declaration: # Deal with variable declaration c_line = c_line.replace("\\=", "\n") c_line = c_line.replace("==", "\t\t") sides = c_line.split("=") sides[1] = "=".join(sides[1:]) sides = [x.replace("\n", "\=") for x in sides] sides = [x.replace("\t\t", "==") for x in sides] c_line = c_line.replace("\n", "=") c_line = c_line.replace("\t\t", "==") sides[0] = parenthesis_parser(sides[0].strip(), VARIABLES, OUTPUT)[0] sides[1] = parenthesis_parser(strip_front(sides[1]), VARIABLES, OUTPUT, var=True)[0] VARIABLES[sides[0]] = sides[1] continue line_info, OUTPUT = parenthesis_parser(c_line.strip(), VARIABLES, OUTPUT) except Exception as e: await message.channel.send(f'{type(e).__name__} in line `{c_line}`:\n\t{e}') return try: await message.channel.send( OUTPUT.replace("<@", "<\@").replace("\\\\", "\t\t").replace("\\", "").replace("\t\t", "\\").replace(u"\uF000","\n",50)[:1950]) except discord.errors.HTTPException: pass try: tag_name tag_vars = db.get_entries("b++variables", columns=["name"], conditions={"tag": tag_name}) for var in VARIABLES.keys(): if var.startswith("__"): if type(VARIABLES[var]) == list: VARIABLES[var] = list_to_array(VARIABLES[var]) if (var,) in tag_vars: db.edit_entry("b++variables", entry={"value": str(VARIABLES[var])}, conditions={"name": var}) continue db.add_entry("b++variables", entry=[var, str(VARIABLES[var]), tag_name]) except: pass return
async def MAIN(message, args, level, perms, SERVER): db = Database() months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ] if level == 1: # If just tc/bd, return info on their birthday found = db.get_entries("birthday", conditions={"id": str(message.author.id)}) if found == []: await message.channel.send( f"""You are yet to register your birthday! You can register by using **{SERVER["PREFIX"]}birthday register `DD/MM` `timezone`**""" .replace("\t", "")) return birthday, tz = found[0][1:] birthday = birthday.split("/") birthday_format = months[int(birthday[1]) - 1] + " " + str(birthday[0]) timezone_f = ("+" if tz > 0 else "") + str(tz) await message.channel.send( f"""**{message.author.name}**'s birthday is set as **{birthday_format}** in **UTC {timezone_f}**.""" ) return if args[1].lower() == "month": if level == 2: chosen_month = datetime.now(timezone.utc).month elif is_whole(args[2]): if int(args[2]) > 12 or int(args[2]) < 1: await message.channel.send( "Invalid month number. If you're picking a month number, choose one between 1 and 12!" ) return chosen_month = int(args[2]) else: possible_months = [ x for x in months if x.lower().startswith(args[2].lower()) ] if len(possible_months) == 0: new_possible = [ x for x in months if args[2].lower() in x.lower() ] if len(new_possible) == 0: await message.channel.send( "There's no valid month with that name!") return if len(new_possible) > 1: await message.channel.send( f"""There are multiple months fitting that search key. Please specify which one you mean! `({', '.join(new_possible)})`""".replace("\t", "")) return possible_months = new_possible if len(possible_months) > 1: await message.channel.send( f"""There are multiple months fitting that search key. Please specify which one you mean! `({', '.join(possible_months)})`""".replace("\t", "")) return chosen_month = months.index(possible_months[0]) + 1 found = db.get_entries("birthday") found = [k for k in found if int(k[1].split("/")[1]) == chosen_month] month_name = months[chosen_month - 1] if len(found) == 0: await message.channel.send( f"There are no registered birthdays in {month_name}!") return found = sorted(found, key=lambda k: int(k[1].split("/")[0])) messages = [ f"Here are all the birthdays registered in {month_name}:\n\n" ] for bd in found: try: username = f"**{SERVER['MAIN'].get_member(int(bd[0])).name}**" except Exception: username = f"**`[{bd[0]}]`**" day = bd[1].split("/")[0] tz = ("+" if bd[2] > 0 else "") + str(bd[2]) line = f"> {username} - {month_name} {day}, UTC {tz}\n" if len(messages[-1]) + len(line) > 1900: messages.append("") messages[-1] += line for m in messages: await message.channel.send(m) return if args[1].lower() == "next": found = db.get_entries("birthday") found = sorted(found, key=lambda k: int(k[1].split("/")[0])) found = sorted(found, key=lambda k: int(k[1].split("/")[1])) day, month = datetime.now(timezone.utc).day, datetime.now( timezone.utc).month for bd in found: if int(bd[1].split("/")[1]) > month: next_bd = bd break elif int(bd[1].split("/")[1]) == month and int( bd[1].split("/")[0]) > day: next_bd = bd break else: next_bd = found[0] next_id, birthday, tz = next_bd birthday = birthday.split("/") birthday_format = months[int(birthday[1]) - 1] + " " + str( int(birthday[0])) timezone_f = ("+" if tz > 0 else "") + str(tz) try: username = SERVER["MAIN"].get_member(int(next_id)).name except AttributeError: username = next_id await message.channel.send( f"The next birthday is **{username}**'s, on **{birthday_format}** in **UTC {timezone_f}**." ) return if args[1].lower() == "user": if level == 2: await message.channel.send( "Include the username or ID of the person whose birthday you want to check." ) return rest = " ".join(args[2:]) if rest.startswith("<@") and rest.endswith(">"): rest = rest[2:-1] if is_whole(rest): found = db.get_entries("birthday", conditions={"id": rest}) try: username = SERVER["MAIN"].get_member(int(rest)).name except: username = rest if found == []: await message.channel.send( f"**{username}** has not registered a birthday yet!") return user_bd = found[0] birthday, tz = user_bd[1:] birthday = birthday.split("/") birthday_format = months[int(birthday[1]) - 1] + " " + str( int(birthday[0])) timezone_f = ("+" if tz > 0 else "") + str(tz) await message.channel.send( f"**{username}**'s birthday is on **{birthday_format}** in **UTC {timezone_f}**." ) return else: user = discord.utils.get(SERVER["MAIN"].members, name=rest) if user is None: await message.channel.send("That user is not in the server!") return found = db.get_entries("birthday", conditions={"id": str(user.id)}) if found == []: await message.channel.send( f"**{rest}** has not registered a birthday yet!") return user_bd = found[0] birthday, tz = user_bd[1:] birthday = birthday.split("/") birthday_format = months[int(birthday[1]) - 1] + " " + str( int(birthday[0])) timezone_f = ("+" if tz > 0 else "") + str(tz) await message.channel.send( f"**{rest}**'s birthday is on **{birthday_format}** in **UTC {timezone_f}**." ) return if args[1].lower() == "remove": found = db.get_entries("birthday", conditions={"id": str(message.author.id)}) if found == []: await message.channel.send( "You haven't registered a birthday yet to remove it!") return await message.channel.send( f"""Are you sure you want to remove your birthday from the database? Send `confirm` in this channel to confirm. Send anything else to cancel.""".replace( "\n", "").replace("\t", "")) # Wait for a message by the same author in the same channel msg = await BRAIN.wait_for( 'message', check=(lambda m: m.channel == message.channel and m.author == message.author)) if msg.content.lower( ) != "confirm": # If it's not `confirm`, cancel command await message.channel.send("Birthday registering cancelled.") return db.remove_entry("birthday", conditions={"id": str(message.author.id)}) await message.channel.send( "Your birthday has been removed from the database.") return if args[1].lower() == "register": if level == 2: await message.channel.send( "Include your birthday in `DD/MM` to register!") return # Check if the person is in the birthday database or not found = db.get_entries("birthday", conditions={"id": str(message.author.id)}) birthday = args[2].split("/") if level == 3: tz = 0 elif not is_whole(args[3]): await message.channel.send( "Invalid timezone! Make sure it's a whole number from -12 to 14!" ) return elif not -12 <= int(args[3]) <= 14: await message.channel.send( "Invalid timezone! Make sure it's a whole number from -12 to 14!" ) return else: tz = int(args[3]) if len(birthday) != 2: # If it's not `n/n` await message.channel.send( "Invalid birthday! Make sure it's in the `DD/MM` format!") return if not is_whole(birthday[0]) or not is_whole( birthday[1]): # If day and month aren't numbers await message.channel.send( "Invalid birthday! Make sure the day and month are both numbers!" ) return # Transform into integers for these next two checks birthday[0] = int(birthday[0]) birthday[1] = int(birthday[1]) if not 1 <= birthday[1] <= 12: # If month is invalid await message.channel.send( "Invalid month! Make sure it's between 1 and 12.") return if not 1 <= birthday[0] <= monthrange( 2020, birthday[1])[1]: # monthrange checks days in the month await message.channel.send( # 2020 months because it's a leap year, and 29/02 should be available f"Invalid day! Make sure it's between 1 and {monthrange(2020, birthday[1])[1]} for that month." ) return birthday_format = months[birthday[1] - 1] + " " + str(birthday[0]) birthday = "/".join([str(x) for x in birthday ]) # Join the list again for the next few lines timezone_f = ("+" if tz > 0 else "") + str(tz) # This confirmation message cannot be bypassed await message.channel.send( f"""Are you sure you want to record your birthday as {birthday_format} and your timezone as UTC {timezone_f}? Send `confirm` in this channel to confirm. """.replace("\n", "").replace("\t", "")) # Wait for a message by the same author in the same channel msg = await BRAIN.wait_for( 'message', check=(lambda m: m.channel == message.channel and m.author == message.author)) if msg.content.lower( ) != "confirm": # If it's not `confirm`, cancel command await message.channel.send("Birthday registering cancelled.") return # If confirmation passed, record the birthday if found == []: is_new = "" db.add_entry("birthday", [message.author.id, birthday, tz]) else: is_new = "new " db.edit_entry("birthday", entry={ "birthday": birthday, "timezone": tz }, conditions={"id": str(message.author.id)}) await message.channel.send( f"Successfully recorded your {is_new}birthday as **{birthday} UTC {timezone_f}**!" ) return
async def MAIN(message, args, level, perms, SERVER): if level == 1: await message.channel.send("Include a subcommand!") return if args[1].lower() == "setup": if level == 2: n = 10 elif is_whole(args[2]): n = int(args[2]) else: n = 10 msg_ids = [str(message.channel.id)] for _ in range(n): msg = await message.channel.send("\u200b") msg_ids.append(str(msg.id)) await message.channel.send(" ".join(msg_ids)) return if args[1].lower() == "update": await message.channel.send("Updating list...") await SERVER["EVENTS"]["SIGNUPS"].update_list(update_channel=True) await message.channel.send("Updated list!") return if args[1].lower() == "edit": msg = message.content if "name:[" not in msg: await message.channel.send( "Include the name of the TWOW you want to edit!") return db = Database() starting_bound = msg[msg.find("name:[") + 6:] twow_name = starting_bound[:starting_bound.find("]")] twow_list = db.get_entries("signuptwows", conditions={"name": twow_name}) if len(twow_list) == 0: await message.channel.send( f"There's no TWOW named **{twow_name}** in the signup list!") return old_entry = twow_list[0] old_entry = dict( zip(["name", "hosts", "link", "description", "time", "verified"], old_entry)) entry = { "name": None, "hosts": None, "link": None, "description": None, "time": None, "verified": None } cond = {"name": twow_name} if "newname:[" in msg: starting_bound = msg[msg.find("newname:[") + 9:] new_name = starting_bound[:starting_bound.find("]")] entry["name"] = new_name if "host:[" in msg: starting_bound = msg[msg.find("host:[") + 6:] hosts = starting_bound[:starting_bound.find("]")] entry["hosts"] = hosts if "link:[" in msg: starting_bound = msg[msg.find("link:[") + 6:] link = starting_bound[:starting_bound.find("]")].replace( "<", "").replace(">", "") entry["link"] = link if "desc:[" in msg: starting_bound = msg[msg.find("desc:[") + 6:] desc = starting_bound[:starting_bound.find("]")] entry["description"] = desc if "deadline:[" in msg: starting_bound = msg[msg.find("deadline:[") + 10:] dl_string = starting_bound[:starting_bound.find("]")] deadline = datetime.datetime.strptime(dl_string, "%d/%m/%Y %H:%M") deadline = deadline.replace( tzinfo=datetime.timezone.utc).timestamp() entry["time"] = deadline if "verified:[" in msg: starting_bound = msg[msg.find("verified:[") + 10:] verified = starting_bound[:starting_bound.find("]")] if verified in ["0", ""]: vf = 0 else: vf = 1 entry["verified"] = vf entry = {k: d for k, d in entry.items() if d is not None} if len(entry.keys()) == 0: await message.channel.send("You've made no edits to this TWOW!") return db.edit_entry("signuptwows", entry=entry, conditions=cond) announce = "dont_announce" not in msg await SERVER["EVENTS"]["SIGNUPS"].update_list(announce=announce) old_info_string = "" for k, v in old_entry.items(): if v != "": tag = k if k == "hosts": tag = "host" if k == "time": tag = "deadline" if k == "description": tag = "desc" old_info_string += f"{tag}:[{v}] " for k, v in entry.items(): old_entry[k] = v new_info_string = "" for k, v in old_entry.items(): if v != "": tag = k if k == "hosts": tag = "host" if k == "time": tag = "deadline" if k == "description": tag = "desc" if k == "link": v = f"<{v}>" new_info_string += f"{tag}:[{v}] " await message.channel.send( f"""**{cond['name']}** has been edited in the signup list. **Old TWOW Info**: {old_info_string} **New TWOW Info**: {new_info_string}""".replace("\t", "")) if args[1].lower() == "remove": msg = message.content if level == 2: await message.channel.send( "Include the name of the TWOW you want to remove!") return db = Database() if "dont_announce" in msg: twow_name = " ".join(args[2:-1]) else: twow_name = " ".join(args[2:]) twow_list = db.get_entries("signuptwows", conditions={"name": twow_name}) if len(twow_list) == 0: await message.channel.send( f"There's no TWOW named **{twow_name}** in the signup list!") return twow_info = twow_list[0] dl_format = datetime.datetime.utcfromtimestamp( twow_info[4]).strftime("%d/%m/%Y %H:%M") db.remove_entry("signuptwows", conditions={"name": twow_name}) announce = "dont_announce" not in msg await SERVER["EVENTS"]["SIGNUPS"].update_list(announce=announce) await message.channel.send( f"""**{twow_info[0]}** has been removed from the signup list! **TWOW Info**: """.replace("\t", "") + f"""name:[{twow_info[0]}] host:[{twow_info[1]}] link:[{twow_info[2]}] desc:[{twow_info[3]}] deadline:[{dl_format}] {'is_verified' if bool(twow_info[5]) else ''}""".replace("\n", "").replace( "\t", "")) return if args[1].lower() == "add": msg = message.content if "name:[" not in msg: await message.channel.send( "Include the name of the TWOW you want to add!") return db = Database() starting_bound = msg[msg.find("name:[") + 6:] twow_name = starting_bound[:starting_bound.find("]")] entry = [twow_name, "", "", "", 0, 0, ""] if "host:[" in msg: starting_bound = msg[msg.find("host:[") + 6:] hosts = starting_bound[:starting_bound.find("]")] entry[1] = hosts if "link:[" in msg: starting_bound = msg[msg.find("link:[") + 6:] link = starting_bound[:starting_bound.find("]")].replace( "<", "").replace(">", "") entry[2] = link if "desc:[": starting_bound = msg[msg.find("desc:[") + 6:] desc = starting_bound[:starting_bound.find("]")] entry[3] = desc if "deadline:[" in msg: starting_bound = msg[msg.find("deadline:[") + 10:] deadline = starting_bound[:starting_bound.find("]")] entry[6] = deadline deadline = datetime.datetime.strptime(deadline, "%d/%m/%Y %H:%M") deadline = deadline.replace( tzinfo=datetime.timezone.utc).timestamp() entry[4] = deadline vf = 0 if "verified:[" in msg: starting_bound = msg[msg.find("verified:[") + 10:] verified = starting_bound[:starting_bound.find("]")] if verified not in ["0", ""]: vf = 1 entry[5] = vf db.add_entry("signuptwows", entry[:6]) announce = "dont_announce" not in msg await SERVER["EVENTS"]["SIGNUPS"].update_list(announce=announce) await message.channel.send( f"""**{entry[0]}** has been added to the list of TWOWs in signups! **Host:** {entry[1]} **Description:** {entry[3]} **Deadline:** {entry[6]} **Deadline Timestamp:** {entry[4]} **Link:** <{entry[2]}>""".replace("\t", ""))
async def MAIN(message, args, level, perms, SERVER): if level == 1: await message.channel.send("Include a subcommand!") return db = Database() if args[1].lower() == "info": tag_list = db.get_entries("b++2programs", columns=[ "name", "program", "author", "uses", "created", "lastused" ]) tag_list = sorted(tag_list, reverse=True, key=lambda m: m[3]) tag_leaderboard = False if level == 2: # If it's not specified, assume it's the first page tag_list = tag_list[:10] page = 1 tag_leaderboard = True elif is_whole(args[2]): if (int(args[2]) - 1) * 10 >= len( tag_list): # Detect if the page number is too big await message.channel.send( f"There is no page {args[2]} on the New B++ program list!") return else: # This means the user specified a valid page number lower = (int(args[2]) - 1) * 10 upper = int(args[2]) * 10 tag_list = tag_list[lower:upper] page = int(args[2]) tag_leaderboard = True if tag_leaderboard: beginning = f"```diff\nB++ Programs Page {page}\n\n" for program in tag_list: r = tag_list.index(program) + 1 + (page - 1) * 10 line = f"{r}{' '*(2-len(str(r)))}: {program[0]} :: {program[3]} use{'s' if program[3] != 1 else ''}" member_id = program[2] try: # Try to gather a username from the ID member = SERVER["MAIN"].get_member(int(member_id)).name except: # If you can't, just display the ID member = str(member_id) created_on = dt.utcfromtimestamp( program[4]).strftime('%Y-%m-%d %H:%M:%S UTC') line += f" (written by {member} at {created_on})\n" beginning += line # Add this line to the final message beginning += "```" # Close off code block await message.channel.send(beginning) return tag_name = args[2] if tag_name not in [x[0] for x in tag_list]: await message.channel.send("That tag does not exist.") return program = tag_list[[x[0] for x in tag_list].index(tag_name)] member_id = program[2] try: # Try to gather a username from the ID member = SERVER["MAIN"].get_member(int(member_id)).name except: # If you can't, just display the ID member = str(member_id) created_on = dt.utcfromtimestamp( program[4]).strftime('%Y-%m-%d %H:%M:%S UTC') c_d = dt.now() - dt.utcfromtimestamp(program[4]) d = c_d.days h, rm = divmod(c_d.seconds, 3600) m, s = divmod(rm, 60) c_d = (('' if d == 0 else f'{d} day{"s" if d!=1 else ""}, ') + ('' if h == 0 else f'{h} hour{"s" if h!=1 else ""}, ') + ('' if m == 0 else f'{m} minute{"s" if m!=1 else ""}, ') + (f'{s} second{"s" if s!=1 else ""}')) msg = f"**{program[0]}** -- by {member} -- {program[3]} use{'s' if program[3]!=1 else ''}\n" msg += f"Created on {created_on} `({c_d} ago)`\n" if program[5] != 0: last_used = dt.utcfromtimestamp( program[5]).strftime('%Y-%m-%d %H:%M:%S UTC') u_d = dt.now() - dt.utcfromtimestamp(program[5]) d = u_d.days h, rm = divmod(u_d.seconds, 3600) m, s = divmod(rm, 60) u_d = (('' if d == 0 else f'{d} day{"s" if d!=1 else ""}, ') + ('' if h == 0 else f'{h} hour{"s" if h!=1 else ""}, ') + ('' if m == 0 else f'{m} minute{"s" if m!=1 else ""}, ') + (f'{s} second{"s" if s!=1 else ""}')) msg += f"Last used on {last_used} `({u_d} ago)`\n" if len(program[1]) > 1700: msg += f"The program is too long to be included in the message, so it's in the file below:" open(f'program_{program[0]}.txt', 'w', encoding="utf-8").write(program[1]) await message.channel.send( msg, file=discord.File(f'program_{program[0]}.txt')) os.remove(f'program_{program[0]}.txt') else: msg += f"```{program[1]}```" await message.channel.send(msg) return if args[1].lower() == "create": if level == 2: await message.channel.send("Include the name of your new program!") return tag_name = args[2] if re.search(r"[^0-9A-Za-z_]", tag_name) or re.search( r"[0-9]", tag_name[0]): await message.channel.send( "Tag name can only contain letters, numbers and underscores, and cannot start with a number!" ) return if tag_name in ["create", "edit", "delete", "info", "run", "help"]: await message.channel.send( "The tag name must not be a reserved keyword!") return if len(tag_name) > 30: await message.channel.send( "That tag name is too long. 30 characters maximum.") return if level > 3: program = " ".join(args[3:]) elif len(message.attachments) != 0: try: if message.attachments[0].size >= 20000: await message.channel.send( "Your program must be under **20KB**.") return await message.attachments[0].save(f"Config/{message.id}.txt") except Exception: await message.channel.send("Include a valid program to save!") return program = open(f"Config/{message.id}.txt", "r", encoding="utf-8").read() os.remove(f"Config/{message.id}.txt") else: await message.channel.send("Include a valid program to save!") return while program.startswith("`") and program.endswith("`"): program = program[1:-1] program.replace("{}", "\t") if (tag_name, ) in db.get_entries("b++2programs", columns=["name"]): await message.channel.send( "There's already a program with that name!") return db.add_entry("b++2programs", [tag_name, program, message.author.id, 0, time.time(), 0]) await message.channel.send( f"Successfully created program `{tag_name}`!") return if args[1].lower() == "edit": if level == 2: await message.channel.send( "Include the name of the program you want to edit!") return tag_name = args[2] tag_list = db.get_entries("b++2programs", columns=["name", "author"]) if tag_name not in [x[0] for x in tag_list]: await message.channel.send( f"There's no program under the name `{tag_name}`!") return ind = [x[0] for x in tag_list].index(tag_name) if tag_list[ind][1] != str(message.author.id) and perms < 2: await message.channel.send( f"You can only edit a program if you created it or if you're a staff member!" ) return if level > 3: program = " ".join(args[3:]) elif len(message.attachments) != 0: try: if message.attachments[0].size >= 20000: await message.channel.send( "Your program must be under **20KB**.") return await message.attachments[0].save(f"Config/{message.id}.txt") except Exception: await message.channel.send("Include a valid program to run!") return program = open(f"Config/{message.id}.txt", "r", encoding="utf-8").read() os.remove(f"Config/{message.id}.txt") else: await message.channel.send("Include a valid program to run!") return while program.startswith("`") and program.endswith("`"): program = program[1:-1] program = program.replace("{}", "\v") db.edit_entry("b++2programs", entry={"program": program}, conditions={"name": tag_name}) await message.channel.send(f"Succesfully edited program {tag_name}!") return if args[1].lower() == "delete": if level == 2: await message.channel.send( "Include the name of the program you want to delete!") return tag_name = args[2] tag_list = db.get_entries("b++2programs", columns=["name", "author"]) if tag_name not in [x[0] for x in tag_list]: await message.channel.send( f"There's no program under the name `{tag_name}`!") return ind = [x[0] for x in tag_list].index(tag_name) if tag_list[ind][1] != str(message.author.id) and perms < 2: await message.channel.send( f"You can only edit a program if you created it or if you're a staff member!" ) return db.remove_entry("b++2programs", conditions={"name": tag_name}) await message.channel.send(f"Succesfully deleted program {tag_name}!") return if args[1].lower() == "run": if level > 2: program = " ".join(args[2:]) elif len(message.attachments) != 0: try: if message.attachments[0].size >= 20000: await message.channel.send( "Your program must be under **20KB**.") return await message.attachments[0].save(f"Config/{message.id}.txt") except Exception: await message.channel.send("Include a valid program to run!") return program = open(f"Config/{message.id}.txt", "r", encoding="utf-8").read() os.remove(f"Config/{message.id}.txt") else: await message.channel.send("Include a valid program to run!") return while program.startswith("`") and program.endswith("`"): program = program[1:-1] program = program.replace("{}", "\v") program_args = [] author = message.author.id runner = message.author else: tag_name = args[1] tag_list = db.get_entries( "b++2programs", columns=["name", "program", "author", "uses"]) if tag_name not in [x[0] for x in tag_list]: await message.channel.send( f"There's no program under the name `{tag_name}`!") return tag_info = [x for x in tag_list if x[0] == tag_name][0] program = tag_info[1] uses = tag_info[3] + 1 db.edit_entry("b++2programs", entry={ "uses": uses, "lastused": time.time() }, conditions={"name": tag_name}) program_args = args[2:] author = tag_info[2] runner = message.author try: program_output = run_bpp_program(program, program_args, author, runner) program_output = program_output.replace("<@", "<\\@") except Exception as e: await message.channel.send(f'{type(e).__name__}:\n```{e}```') return if len(program_output) > 1950: program_output = "⚠️ `Output too long! First 1900 characters:`\n\n" + program_output[: 1900] if len(program_output.strip()) == 0: program_output = "\u200b" await message.channel.send(program_output) return