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): """ 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 do(message: discord.Message, python_code: Annotate.Code): """ Execute python code. """ code_globals.update( dict(message=message, client=client, author=message.author, server=message.server, channel=message.channel)) # Create an async function so that we can await it using the result of eval python_code = "async def do_session():\n " + "\n ".join( line for line in python_code.split("\n")) try: exec(python_code, code_globals) except SyntaxError as e: await client.say(message, "```" + utils.format_syntax_error(e) + "```") return before = datetime.now() try: result = await eval("do_session()", code_globals) except Exception as e: await client.say(message, "```" + utils.format_exception(e) + "```") else: if result: await send_result(message.channel, result, datetime.now() - before)
def load_plugin(name: str, package: str = "plugins"): """ Load a plugin with the name name. If package isn't specified, this looks for plugin with specified name in /plugins/ Any loaded plugin is imported and stored in the self.plugins dictionary. """ if not name.startswith("__") or not name.endswith("__"): try: plugin = importlib.import_module("{package}.{plugin}".format( plugin=name, package=package)) except ImportError as e: logging.error( "An error occurred when loading plugin {}:\n{}".format( name, format_exception(e))) return False except: logging.error( "An error occurred when loading plugin {}:\n{}".format( name, format_exc())) return False plugins[name] = plugin logging.debug("LOADED PLUGIN " + name) return True return False
def eval_(client: discord.Client, message: discord.Message, python_code: Annotate.Code): """ Evaluate a python expression. Can be any python code on one line that returns something. """ code_globals.update(dict(message=message, client=client)) try: result = eval(python_code, code_globals) except Exception as e: result = utils.format_exception(e) yield from client.say(message, "**Result:** \n```{}\n```".format(result))
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
def do(client: discord.Client, message: discord.Message, python_code: Annotate.Code): """ Execute python code. Coroutines do not work, although you can run `say(msg, c=message.channel)` to send a message, optionally to a channel. Eg: `say("Hello!")`. """ def say(msg, m=message): asyncio.async(client.say(m, msg)) code_globals.update(dict(say=say, message=message, client=client)) try: exec(python_code, code_globals) except Exception as e: say("```" + utils.format_exception(e) + "```")
def main(): """ The main function. Parses command line arguments, sets up logging, gets the user's login info, sets up any background task and starts the bot. """ # Setup logger with level specified in start_args or logging.INFO logging.basicConfig( filename=start_args.log_file, level=start_args.log_level, format="%(levelname)s %(asctime)s [%(module)s / %(name)s]: %(message)s" ) # Always keep the websockets.protocol logger at INFO as a minimum unless --enable-protocol-logging is set if not start_args.enable_protocol_logging: discord_logger = logging.getLogger("websockets.protocol") discord_logger.setLevel(start_args.log_level if start_args. log_level >= logging.INFO else logging.INFO) # Setup some config for more customization bot_meta = config.Config( "bot_meta", pretty=True, data=dict( name="PCBOT", command_prefix=config.default_command_prefix, case_sensitive_commands=config.default_case_sensitive_commands, display_owner_error_in_chat=False)) config.name = bot_meta.data["name"] config.default_command_prefix = bot_meta.data["command_prefix"] config.default_case_sensitive_commands = bot_meta.data[ "case_sensitive_commands"] config.owner_error = bot_meta.data["display_owner_error_in_chat"] # Set the client for the plugins to use plugins.set_client(client) utils.set_client(client) # Load plugin for builtin commands plugins.load_plugin("builtin", "pcbot") # Load all dynamic plugins plugins.load_plugins() # Login with the specified token if specified token = start_args.token or input("Token: ") login = [token] # Setup background tasks client.loop.create_task(add_tasks()) try: client.run(*login) except discord.errors.LoginFailure as e: logging.error(utils.format_exception(e))
async def eval_(message: discord.Message, python_code: Annotate.Code): """ Evaluate a python expression. Can be any python code on one line that returns something. Coroutine generators will by awaited. """ code_globals.update(dict(message=message, client=client, author=message.author, server=message.server, channel=message.channel)) try: result = eval(python_code, code_globals) if inspect.isawaitable(result): result = await result except SyntaxError as e: result = utils.format_syntax_error(e) except Exception as e: result = utils.format_exception(e) await client.say(message, "**Result:** \n```{}\n```".format(result))
async def eval_(message: discord.Message, python_code: Annotate.Code): """ Evaluate a python expression. Can be any python code on one line that returns something. Coroutine generators will by awaited. """ code_globals.update(dict(message=message, client=client, author=message.author, server=message.server, channel=message.channel)) before = datetime.now() try: result = eval(python_code, code_globals) if inspect.isawaitable(result): result = await result except SyntaxError as e: result = utils.format_syntax_error(e) except Exception as e: result = utils.format_exception(e) await send_result(message.channel, result, datetime.now() - before)
async def do(message: discord.Message, python_code: Annotate.Code): """ Execute python code. """ code_globals.update(dict(message=message, client=client, author=message.author, server=message.server, channel=message.channel)) # Create an async function so that we can await it using the result of eval python_code = "async def do_session():\n " + "\n ".join(line for line in python_code.split("\n")) try: exec(python_code, code_globals) except SyntaxError as e: await client.say(message, "```" + utils.format_syntax_error(e) + "```") return try: result = await eval("do_session()", code_globals) except Exception as e: await client.say(message, "```" + utils.format_exception(e) + "```") else: if result: await client.say(message, "**Result:** \n```{}\n```".format(result))
def main(): """ The main function. Parses command line arguments, sets up logging, gets the user's login info, sets up any background task and starts the bot. """ # Add all command-line arguments parser = ArgumentParser(description="Run PCBOT.") parser.add_argument("--version", "-V", help="Return the current version.", action="version", version=__version__) # Setup a login group for handling only token or email, but not both login_group = parser.add_mutually_exclusive_group() login_group.add_argument( "--token", "-t", help="The token to login with. Prompts if omitted.") login_group.add_argument("--email", "-e", help="Alternative email to login with.") parser.add_argument("--new-pass", "-n", help="Always prompts for password.", action="store_true") parser.add_argument( "--log-level", "-l", help= "Use the specified logging level (see the docs on logging for values).", type=lambda s: getattr(logging, s.upper()), default=logging.INFO, metavar="LEVEL") start_args = parser.parse_args() # Setup logger with level specified in start_args or logging.INFO logging.basicConfig( level=start_args.log_level, format="%(levelname)s %(asctime)s [%(module)s / %(name)s]: %(message)s" ) # Always keep discord.py logger at INFO as a minimum discord_logger = logging.getLogger("discord") discord_logger.setLevel(start_args.log_level if start_args. log_level >= logging.INFO else logging.INFO) # Setup some config for more customization bot_meta = config.Config( "bot_meta", pretty=True, data=dict( name="PCBOT", command_prefix=config.default_command_prefix, case_sensitive_commands=config.default_case_sensitive_commands, display_owner_error_in_chat=False)) config.name = bot_meta.data["name"] config.default_command_prefix = bot_meta.data["command_prefix"] config.default_case_sensitive_commands = bot_meta.data[ "case_sensitive_commands"] config.owner_error = bot_meta.data["display_owner_error_in_chat"] # Set the client for the plugins to use plugins.set_client(client) utils.set_client(client) # Load plugin for builtin commands plugins.load_plugin("builtin", "pcbot") # Load all dynamic plugins plugins.load_plugins() # Handle login if not start_args.email: # Login with the specified token if specified token = start_args.token or input("Token: ") login = [token] else: # Get the email from commandline argument email = start_args.email password = "" cached_path = client._get_cache_filename( email) # Get the name of the would-be cached email # If the --new-pass command-line argument is specified, remove the cached password # Useful for when you have changed the password if start_args.new_pass: if os.path.exists(cached_path): os.remove(cached_path) # Prompt for password if the cached file does not exist (the user has not logged in before or # they they entered the --new-pass argument) if not os.path.exists(cached_path): password = getpass() login = [email, password] # Setup background tasks client.loop.create_task(add_tasks()) try: client.run(*login) except discord.errors.LoginFailure as e: logging.error(utils.format_exception(e))
def main(): """ The main function. Parses command line arguments, sets up logging, gets the user's login info, sets up any background task and starts the bot. """ # Add all command-line arguments parser = ArgumentParser(description="Run PCBOT.") parser.add_argument("--version", "-V", help="Return the current version.", action="version", version=__version__) # Setup a login group for handling only token or email, but not both login_group = parser.add_mutually_exclusive_group() login_group.add_argument("--token", "-t", help="The token to login with. Prompts if omitted.") login_group.add_argument("--email", "-e", help="The email to login to. Token prompt is default.") parser.add_argument("--new-pass", "-n", help="Always prompts for password.", action="store_true") parser.add_argument("--log-level", "-l", help="Use the specified logging level (see the docs on logging for values).", type=lambda s: getattr(logging, s.upper()), default=logging.INFO, metavar="LEVEL") start_args = parser.parse_args() # Setup logger with level specified in start_args or logging.INFO logging.basicConfig(level=start_args.log_level, format="%(levelname)s %(asctime)s [%(module)s / %(name)s]: %(message)s") # Always keep discord.py logger at INFO as a minimum discord_logger = logging.getLogger("discord") discord_logger.setLevel(start_args.log_level if start_args.log_level >= logging.INFO else logging.INFO) # Setup some config for more customization bot_meta = config.Config("bot_meta", pretty=True, data=dict( name="PCBOT", command_prefix=config.command_prefix )) config.name = bot_meta.data["name"] config.command_prefix = bot_meta.data["command_prefix"] # Set the client for the plugins to use plugins.set_client(client) # Load plugin for builtin commands plugins.load_plugin("builtin", "pcbot") # Load all dynamic plugins plugins.load_plugins() # Handle login if not start_args.email: # Login with the specified token if specified token = start_args.token or input("Token: ") login = [token] else: # Get the email from commandline argument email = start_args.email password = "" cached_path = client._get_cache_filename(email) # Get the name of the would-be cached email # If the --new-pass command-line argument is specified, remove the cached password # Useful for when you have changed the password if start_args.new_pass: if os.path.exists(cached_path): os.remove(cached_path) # Prompt for password if the cached file does not exist (the user has not logged in before or # they they entered the --new-pass argument) if not os.path.exists(cached_path): password = getpass() login = [email, password] # Setup background tasks client.loop.create_task(add_tasks()) try: client.run(*login) except discord.errors.LoginFailure as e: logging.error(utils.format_exception(e))
def load_plugin(name: str, package: str="plugins"): """ Load a plugin with the name name. If package isn't specified, this looks for plugin with specified name in /plugins/ Any loaded plugin is imported and stored in the self.plugins dictionary. """ if not name.startswith("__") or not name.endswith("__"): try: plugin = importlib.import_module("{package}.{plugin}".format(plugin=name, package=package)) except ImportError as e: logging.error("An error occurred when loading plugin {}:\n{}".format(name, format_exception(e))) return False except: logging.error("An error occurred when loading plugin {}:\n{}".format(name, format_exc())) return False plugins[name] = plugin logging.debug("LOADED PLUGIN " + name) return True return False