#methods.py #Imports. import os, json, discord, random, math, datetime from dotenv import load_dotenv #Load .env file. load_dotenv() PREFIX = os.getenv('BOT_PREFIX') ####################################################################################### ### COMMANDS - ALL COMMANDS MUST BE ALL LOWERCASE, NO SPACES, WITH A PREFIX OF CMD_ ### ####################################################################################### async def cmd_hello(ctx): await ctx.send("Hello, World!") async def cmd_goodbye(ctx): await ctx.send("Goodbye!") async def cmd_whatareyou(ctx): await ctx.send("An idiot sandwich.") #Add points for a user. async def cmd_addpoints(ctx, member: discord.Member = None, number = None): points_data = loadpoints() #Load all point history into a variable. member = member or ctx.author #Set the target equal to the user specified OR the sender of the message. user_id = str(member.id) #Sets the user ID equal to the ID of the user specified. pointAmount = number or 1 #Makes the amount to add either the amount specified, or just 1. points_data[user_id] = points_data.get(user_id, 0) + int(pointAmount) #Add the desired amount of points to the user. loadpoints(points_data) #Reload the points data. await ctx.send(f"{member.mention} now has {points_data[user_id]} points!") #Checks the current points of a user. async def cmd_checkpoints(ctx, member: discord.Member = None): points_data = loadpoints() #Load all point history into a variable. member = member or ctx.author # Checks either the member specified, or the sender of the message. user_id = str(member.id) #Set the user ID equal to the ID of the user specified. points = points_data.get(user_id, 0) #Retrieve the points of the user ID. await ctx.send(f"{member.mention} has {points} points.") #Add a custom command to customcommands.json. async def cmd_addcommand(ctx, command, *message): response = (" ".join(message)) #Takes in the custom message. commands_temp = loadcommands("commands.json") #Load the built-in commands to a temp variable. customcommands_temp = loadcommands("customcommands.json") #Load the custom commands to a temp variable. #Checks to see if the command already exists in commands.json. if command in commands_temp: await ctx.send(f"Command '{command}' already exists in base commands! Not overwriting.") return #Checks to see if the command already exists in customcommands.json. if command in customcommands_temp: await ctx.send(f"Command '{command}' already exists in custom commands! Not overwriting.") return #Takes the response, and adds it to the customcommands.json file. customcommands_temp[command] = response with open("customcommands.json", "w", encoding="utf-8") as file: json.dump(customcommands_temp, file, indent=4) await ctx.send(f"Command '{command}' added successfully!") #Lists all built-in and custom commands currently set up. async def cmd_listcommands(ctx): try: #Loads both custom and built-in commands to temp variables. commands_dict = loadcommands("commands.json") customcommands_dict = loadcommands("customcommands.json") #Adds each set of commands into a list variable, then displays it. commands_list = "\n".join([f"{PREFIX}**{cmd}**" for cmd, resp in commands_dict.items()]) await ctx.send(f"**Available Built-In Commands:**\n\n{commands_list}") #Checks to see if there are any custom commands, and then lists them if there are any. with open ("customcommands.json", 'r') as file: data = json.load(file) if data != {}: customcommands_list = "\n".join([f"{PREFIX}**{cmd}**" for cmd, resp in customcommands_dict.items()]) await ctx.send(f"\n\n**Available Custom Commands:**\n\n{customcommands_list}\n\n") #Exception for failing to load commands. Typically indicates a missing commands.json file. except Exception as e: await ctx.send(f"Error loading commands: {e}") #Rolls a dice roll. Supports modifiers as well. async def cmd_roll(ctx, inputValue, sign = None, addition = None): #Initializing variables for the subtotal and total. subtotal = 0 total = 0 #Rolls the dice. try: #Splits the input into variables separated by the letter 'd', for number of sides, and how many sides. number, sides = map(int, inputValue.lower().split('d')) #For however many times you roll, it passes the number of sides to a rolldie function, and adds the result to subtotal. for _ in range(number): subtotal += rolldie(sides) #Checks to see if any modifiers were applied. If so, apply the logic. if sign and addition: total = subtotal addition = int(addition) #Explicitly converts the modifier value to an integer. if sign == '+': #Addition. total = subtotal + addition elif sign == '-': #Subtraction. total = subtotal - addition elif sign in ('*', 'X', 'x'): #Multiplication. total = subtotal * addition elif sign == '/': #Division, rounding down. total = math.floor(subtotal / addition) else: await ctx.send("Invalid mathematical sign passed.") await ctx.send(f"You rolled a total of {total} ({subtotal} {sign} {addition}).") else: await ctx.send(f"You rolled a total of {subtotal}.") except ValueError as e: await ctx.send(f"Invalid input - {e}.") # Define the rotation start date (Week 1) ROTATION_START_DATE = datetime.date(2025, 7, 14) #@bot.command(name='speedrotation') async def cmd_speedrotation(ctx): # Get today's date today = datetime.date.today() # For this example, assume July 24, 2025 # Calculate days since the start of the rotation days_since_start = (today - ROTATION_START_DATE).days # Calculate current week number (1, 2, or 3) current_week = (days_since_start // 7 % 3) + 1 # Determine the status based on the week number if current_week == 1 or current_week == 2: status = "Work from home" else: # current_week == 3 status = "Working at the office" # Find the Monday of the current week # weekday() returns 0 for Monday, 1 for Tuesday, etc. current_monday = today - datetime.timedelta(days=today.weekday()) # Calculate weeks to add to reach the next Week 3 if current_week == 1: weeks_to_add = 2 elif current_week == 2: weeks_to_add = 1 else: # current_week == 3 weeks_to_add = 3 # Calculate the next Week 3 Monday next_week3_monday = current_monday + datetime.timedelta(weeks=weeks_to_add) # Format the response response = ( f"Speed is currently in **Week {current_week}** ({status}).\n" f"Speed will be back to working at the office on **{next_week3_monday.strftime('%B %d, %Y')}**." ) # Send the response await ctx.send(response) ######################################################## ### INTERNAL METHODS - ALL METHODS MUST BE LOWERCASE ### ######################################################## #Loads commands into variable. def loadcommands(filename): if not os.path.exists(filename): with open(filename, "w", encoding="utf-8") as file: json.dump({}, file) # Create an empty JSON file with open(filename, "r", encoding="utf-8") as file: return json.load(file) #Loads points into variable. def loadpoints(): if not os.path.exists("points.json"): with open("points.json", "w", encoding="utf-8") as file: json.dump({}, file) # Create an empty JSON file with open("points.json", "r", encoding="utf-8") as file: return json.load(file) # Saves points to the points.json file. def savepoints(points_data): with open("points.json", "w", encoding="utf-8") as file: json.dump(points_data, file, indent=4) #Rolls die for cmd_roll def rolldie(sides): return random.randint(1, sides)