async def set_prefix(message: discord.Message, prefix: str = None): """ Set the bot prefix. **The prefix is case sensitive and may not include spaces.** """ config.set_server_config(message.server, "command_prefix", utils.split(prefix)[0] if prefix else None) pre = config.default_command_prefix if prefix is None else prefix await client.say(message, "Set the server prefix to `{}`.".format(pre))
def on_message(client: discord.Client, message: discord.Message): """ Perform lambda commands. """ args = utils.split(message.content) # Check if the command is a lambda command and is not disabled (in the blacklist) if args[0] in lambdas.data and args[0] not in lambda_config.data["blacklist"]: def say(msg, m=message): asyncio.async(client.say(m, msg)) def arg(i, default=0): if len(args) > i: return args[i] else: return default code_globals.update(dict(arg=arg, say=say, args=args, message=message, client=client)) # Execute the command try: exec(lambdas.data[args[0]], code_globals) except Exception as e: if utils.is_owner(message.author): say("```" + utils.format_exception(e) + "```") else: logging.warn("An exception occurred when parsing lambda command:" "\n{}".format(utils.format_exception(e))) return True
async def on_message(message: discord.Message): """ What to do on any message received. The bot will handle all commands in plugins and send on_message to plugins using it. """ # Make sure the client is ready before processing commands await client.wait_until_ready() start_time = datetime.now() # We don't care about channels we can't write in as the bot usually sends feedback if message.server and message.server.owner and not message.server.me.permissions_in( message.channel).send_messages: return # Don't accept commands from bot accounts if message.author.bot: return # Split content into arguments by space (surround with quotes for spaces) cmd_args = utils.split(message.content) # Get command name if cmd_args[0].startswith(config.command_prefix) and len( cmd_args[0]) > len(config.command_prefix): cmd = cmd_args[0][len(config.command_prefix):] else: return # Try finding a command object command = plugins.get_command(cmd) if not command: return # Parse the command with the user's arguments try: parsed_command, args, kwargs = await parse_command( command, cmd_args, message) except AssertionError as e: # Return any feedback given from the command via AssertionError, or the command help await client.send_message( message.channel, str(e) or utils.format_help(command, no_subcommand=True)) log_message(message) return if not parsed_command: return log_message(message) client.loop.create_task( execute_command(parsed_command, message, *args, **kwargs)) # Run command # Log time spent parsing the command stop_time = datetime.now() time_elapsed = (stop_time - start_time).total_seconds() / 1000 logging.debug("Time spent parsing command: {elapsed:.6f}ms".format( elapsed=time_elapsed))
async def on_message(message: discord.Message): """ Perform lambda commands. """ args = utils.split(message.content) # Check if the command is a lambda command and is not disabled (in the blacklist) if args[0] in lambdas.data and args[0] not in lambda_config.data[ "blacklist"]: def arg(i, default=0): if len(args) > i: return args[i] else: return default code_globals.update( dict(arg=arg, args=args, message=message, client=client, author=message.author, server=message.server, channel=message.channel)) python_code = lambdas.data[args[0]] # Create an async function so that we can await it using the result of eval python_code = "async def lambda_session():\n " + "\n ".join( line for line in python_code.split("\n")) try: exec(python_code, code_globals) except SyntaxError as e: if plugins.is_owner(message.author): await client.say(message, "```" + utils.format_syntax_error(e) + "```") else: logging.warning( "An exception occurred when parsing lambda command:" "\n{}".format(utils.format_syntax_error(e))) return True # Execute the command try: await eval("lambda_session()", code_globals) except AssertionError as e: # Send assertion errors to the core module raise AssertionError(e) except Exception as e: if plugins.is_owner(message.author): await client.say(message, "```" + utils.format_exception(e) + "```") else: logging.warning( "An exception occurred when parsing lambda command:" "\n{}".format(utils.format_exception(e))) return True
async def on_message(message: discord.Message): success = False # User alias check if message.author.id in aliases.data: user_aliases = aliases.data[message.author.id] # Check any aliases for name, command in user_aliases.items(): execute = False msg = message.content args = utils.split(msg) if not command.get("case_sensitive", False): msg = msg.lower() if command.get("anywhere", False): if name in msg: execute = True else: if name == args[0]: execute = True if execute: if command.get("delete_message", False): if message.server.me.permissions_in( message.channel).manage_messages: client.loop.create_task(client.delete_message(message)) text = command["text"] pre = config.server_command_prefix(message.server) # Execute the command if it is one if text.startswith(pre): await plugins.execute( utils.split(text)[0][len(pre):], message) else: await client.say(message, text) success = True return success
def parse_annotation(param: inspect.Parameter, default, arg: str, index: int, message: discord.Message): """ Parse annotations and return the command to use. index is basically the arg's index in shelx.split(message.content) """ if default is param.empty: default = None if param.annotation is not param.empty: # Any annotation is a function or Annotation enum anno = param.annotation # Valid enum checks if isinstance(anno, utils.Annotate): content = lambda s: utils.split(s, maxsplit=index)[-1].strip("\" ") if anno is utils.Annotate.Content: # Split and get raw content from this point return content(message.content) or default elif anno is utils.Annotate.LowerContent: # Lowercase of above check return content(message.content).lower() or default elif anno is utils.Annotate.CleanContent: # Split and get clean raw content from this point return content(message.clean_content) or default elif anno is utils.Annotate.LowerCleanContent: # Lowercase of above check return content(message.clean_content).lower() or default elif anno is utils.Annotate.Member: # Checks member names or mentions return utils.find_member(message.server, arg) or default_self(anno, default, message) elif anno is utils.Annotate.Channel: # Checks channel names or mentions return utils.find_channel(message.server, arg) or default_self(anno, default, message) elif anno is utils.Annotate.Code: # Works like Content but extracts code return utils.get_formatted_code(utils.split(message.content, maxsplit=index)[-1]) or default try: # Try running as a method result = anno(arg) return result if result is not None else default except TypeError: raise TypeError("Command parameter annotation must be either pcbot.utils.Annotate or a callable") except: # On error, eg when annotation is int and given argument is str return None return str(arg) or default # Return str of arg if there was no annotation
async def on_message(message: discord.Message): """ What to do on any message received. The bot will handle all commands in plugins and send on_message to plugins using it. """ # Make sure the client is ready before processing commands await client.wait_until_ready() start_time = datetime.now() # We don't care about channels we can't write in as the bot usually sends feedback if not message.channel.is_private and not message.server.me.permissions_in(message.channel).send_messages: return # Don't accept commands from bot accounts if message.author.bot: return # Split content into arguments by space (surround with quotes for spaces) cmd_args = utils.split(message.content) # Get command name cmd = "" if cmd_args[0].startswith(config.command_prefix) and len(cmd_args[0]) > len(config.command_prefix): cmd = cmd_args[0][len(config.command_prefix):] # Handle commands for plugin in plugins.all_values(): # If there was a command and the bot can send messages in the channel, parse the command if not cmd: continue command = plugins.get_command(plugin, cmd) if command: parsed_command, args, kwargs = await parse_command(command, cmd_args, message) if parsed_command: log_message(message) # Log the command client.loop.create_task(execute_command(parsed_command, message, *args, **kwargs)) # Run command # Log time spent parsing the command stop_time = datetime.now() time_elapsed = (stop_time - start_time).total_seconds() / 1000 logging.debug("Time spent parsing command: {elapsed:.6f}ms".format(elapsed=time_elapsed))
async def on_message(message: discord.Message): success = False # User alias check if message.author.id in aliases.data: user_aliases = aliases.data[message.author.id] # Check any aliases for name, command in user_aliases.items(): execute = False msg = message.content if not command.get("case_sensitive", False): msg = msg.lower() if command.get("anywhere", False): if name in msg: execute = True else: if msg.startswith(name): execute = True if execute: if command.get("delete_message", False): if message.server.me.permissions_in( message.channel).manage_messages: asyncio.ensure_future(client.delete_message(message)) text = command["text"] if text.startswith(config.command_prefix): args = utils.split(text) # try: print(args, "\n", args[0], *args[1:]) await plugins.execute(args[0][1:], message, *args[1:]) # except: # pass # else: # return True await client.say(message, text) success = True return success
async def on_message(message: discord.Message): """ Perform lambda commands. """ args = utils.split(message.content) # Check if the command is a lambda command and is not disabled (in the blacklist) if args[0] in lambdas.data and args[0] not in lambda_config.data["blacklist"]: def arg(i, default=0): if len(args) > i: return args[i] else: return default code_globals.update(dict(arg=arg, args=args, message=message, client=client, author=message.author, server=message.server, channel=message.channel)) python_code = lambdas.data[args[0]] # Create an async function so that we can await it using the result of eval python_code = "async def lambda_session():\n " + "\n ".join(line for line in python_code.split("\n")) try: exec(python_code, code_globals) except SyntaxError as e: if utils.is_owner(message.author): await client.say(message, "```" + utils.format_syntax_error(e) + "```") else: logging.warn("An exception occurred when parsing lambda command:" "\n{}".format(utils.format_syntax_error(e))) return True # Execute the command try: await eval("lambda_session()", code_globals) except AssertionError as e: # Send assertion errors to the core module raise AssertionError(e) except Exception as e: if utils.is_owner(message.author): await client.say(message, "```" + utils.format_exception(e) + "```") else: logging.warn("An exception occurred when parsing lambda command:" "\n{}".format(utils.format_exception(e))) finally: return True
async def parse_annotation(param: inspect.Parameter, default, arg: str, index: int, message: discord.Message): """ Parse annotations and return the command to use. index is basically the arg's index in shelx.split(message.content) """ if default is param.empty: default = None if param.annotation is not param.empty: # Any annotation is a function or Annotation enum anno = override_annotation(param.annotation) content = lambda s: utils.split(s, maxsplit=index)[-1].strip("\" ") # Valid enum checks if isinstance(anno, utils.Annotate): if anno is utils.Annotate.Content: # Split and get raw content from this point return content(message.content) or default elif anno is utils.Annotate.LowerContent: # Lowercase of above check return content(message.content).lower() or default elif anno is utils.Annotate.CleanContent: # Split and get clean raw content from this point return content(message.clean_content) or default elif anno is utils.Annotate.LowerCleanContent: # Lowercase of above check return content(message.clean_content).lower() or default elif anno is utils.Annotate.Member: # Checks member names or mentions return utils.find_member(message.server, arg) or default_self( anno, default, message) elif anno is utils.Annotate.Channel: # Checks text channel names or mentions return utils.find_channel(message.server, arg) or default_self( anno, default, message) elif anno is utils.Annotate.VoiceChannel: # Checks voice channel names or mentions return utils.find_channel(message.server, arg, channel_type="voice") elif anno is utils.Annotate.Code: # Works like Content but extracts code return utils.get_formatted_code( utils.split(message.content, maxsplit=index)[-1]) or default try: # Try running as a method if getattr(anno, "allow_spaces", False): arg = content(message.content) # Pass the message if the argument has this specified if getattr(anno, "pass_message", False): result = anno(message, arg) else: result = anno(arg) # The function can be a coroutine if inspect.isawaitable(result): result = await result return result if result is not None else default except TypeError: raise TypeError( "Command parameter annotation must be either pcbot.utils.Annotate, a callable or a coroutine" ) except AssertionError as e: # raise the error in order to catch it at a lower level raise AssertionError(e) except: # On error, eg when annotation is int and given argument is str return None return str(arg) or default # Return str of arg if there was no annotation
async def on_message(message: discord.Message): """ What to do on any message received. The bot will handle all commands in plugins and send on_message to plugins using it. """ # Make sure the client is ready before processing commands await client.wait_until_ready() start_time = datetime.utcnow() # Make a local copy of the message since some attributes are changed and they shouldn't be overridden # in plugin based on_message events original_message = message message = copy(message) # We don't care about channels we can't write in as the bot usually sends feedback if message.server and message.server.owner and not message.server.me.permissions_in( message.channel).send_messages: return # Don't accept commands from bot accounts if message.author.bot: return # Find server specific settings command_prefix = config.server_command_prefix(message.server) case_sensitive = config.server_case_sensitive_commands(message.server) # Check that the message is a command if not message.content.startswith(command_prefix): return # Remove the prefix and make sure that a command was actually specified message.content = message.content[len(command_prefix):] if not message.content or message.content.startswith(" "): return # Split content into arguments by space (surround with quotes for spaces) cmd_args = utils.split(message.content) # Try finding a command object using the command name (first argument) command = plugins.get_command(cmd_args[0], case_sensitive=case_sensitive) if not command: return try: # Find the subcommand if there is one command = plugins.get_sub_command(command, *cmd_args[1:], case_sensitive=case_sensitive) # Check that the author is allowed to use the command if not plugins.can_use_command(command, message.author, message.channel): return # Parse the command with the user's arguments parsed_command, args, kwargs = await parse_command( command, cmd_args, message) except AssertionError as e: # Return any feedback given from the command via AssertionError, or the command help await client.send_message( message.channel, str(e) or plugins.format_help( command, message.server, no_subcommand=True)) log_message(message) return if not parsed_command: return # Log the command executed and execute said command log_message(original_message) client.loop.create_task( execute_command(parsed_command, original_message, *args, **kwargs)) # Manually dispatch an event for when commands are requested client.dispatch("command_requested", message, parsed_command, *args, **kwargs) # Log time spent parsing the command stop_time = datetime.utcnow() time_elapsed = (stop_time - start_time).total_seconds() * 1000 logging.debug("Time spent parsing command: {elapsed:.6f}ms".format( elapsed=time_elapsed))
def content(s): return utils.split(s, maxsplit=index)[-1].strip("\" ")