v0.0.2: answer capability

This commit is contained in:
klemek
2021-01-11 19:56:59 +01:00
parent 3ad0b7f1b0
commit f1054f78bb
4 changed files with 82 additions and 34 deletions
+5
View File
@@ -115,6 +115,10 @@ bot.start() # blocking function
* Change the game status every n seconds. * Change the game status every n seconds.
* `error_restart_delay` (default: `2`) * `error_restart_delay` (default: `2`)
* On crash, restart after n seconds. * On crash, restart after n seconds.
* `answer` (default: `True`)
* Use the answer capability on `help` and `info` functions
* `answer_mention` (default: `True`)
* Mention author in the answer
### Registering commands ### Registering commands
@@ -325,6 +329,7 @@ bot.start() # this bot respond to "|help", "|info" and "|hello"
## Versions ## Versions
* v0.0.2 : new answer capability
* v0.0.1 : initial version * v0.0.1 : initial version
## TODO ## TODO
+72 -29
View File
@@ -13,7 +13,9 @@ from dotenv import load_dotenv
from ._utils import sanitize_input, parse_arguments from ._utils import sanitize_input, parse_arguments
CommandFunction = Callable[[discord.Client, discord.Message, Tuple[str]], Coroutine[Any, Any, None]] CommandFunction = Callable[
[discord.Client, discord.Message, Tuple[str]], Coroutine[Any, Any, None]
]
def debug(message: discord.Message, txt: str): def debug(message: discord.Message, txt: str):
@@ -21,7 +23,9 @@ def debug(message: discord.Message, txt: str):
class Command(object): class Command(object):
def __init__(self, regex: str, compute: CommandFunction, help_short: str, help_long: str): def __init__(
self, regex: str, compute: CommandFunction, help_short: str, help_long: str
):
self.regex = regex self.regex = regex
self.compute = compute self.compute = compute
self.help_short = help_short self.help_short = help_short
@@ -41,6 +45,8 @@ class Bot(object):
self.lower_command_names = True self.lower_command_names = True
self.game_change_delay = 10 self.game_change_delay = 10
self.error_restart_delay = 2 self.error_restart_delay = 2
self.answer = True
self.answer_mention = False
# config vars # config vars
self.app_name = app_name self.app_name = app_name
self.version = version self.version = version
@@ -52,11 +58,11 @@ class Bot(object):
self.__watcher = None self.__watcher = None
self.__commands = [] self.__commands = []
self.__fallback = None self.__fallback = None
self.games = [f"v{version}", self.games = [f"v{version}", lambda: f"{len(self.client.guilds)} guilds"]
lambda:f"{len(self.client.guilds)} guilds"]
if self.alias is not None: if self.alias is not None:
self.games += [f"{self.alias}help"] self.games += [f"{self.alias}help"]
self.client = discord.Client() self.client = discord.Client()
self.client.bot = self
self.__register_events() self.__register_events()
self.__register_commands() self.__register_commands()
@@ -68,22 +74,23 @@ class Bot(object):
def __register_commands(self): def __register_commands(self):
# register default commands # register default commands
tmp_alias = '' if self.alias is None else self.alias tmp_alias = "" if self.alias is None else self.alias
self.register_command( self.register_command(
"(help|h)", self.help, "help: show this help", "(help|h)",
self.help,
"help: show this help",
f"```\n" f"```\n"
f"* {tmp_alias}help\n" f"* {tmp_alias}help\n"
f"\tShows the list of commands.\n" f"\tShows the list of commands.\n"
f"* {tmp_alias}help [command]\n" f"* {tmp_alias}help [command]\n"
f"\tShows help about a specific command.\n" f"\tShows help about a specific command.\n"
f"```" f"```",
) )
self.register_command( self.register_command(
"(info|about)", self.info, "info: show description", "(info|about)",
f"```\n" self.info,
f"* {tmp_alias}info:\n" "info: show description",
f"\tShows this bot's status.\n" f"```\n" f"* {tmp_alias}info:\n" f"\tShows this bot's status.\n" f"```",
f"```"
) )
def __generate_game(self) -> str: def __generate_game(self) -> str:
@@ -99,35 +106,55 @@ class Bot(object):
f"{self.app_name} v{self.version}\n" f"{self.app_name} v{self.version}\n"
f"* Started at {self.__t0:%Y-%m-%d %H:%M}\n" f"* Started at {self.__t0:%Y-%m-%d %H:%M}\n"
f"* Connected to {len(self.client.guilds)} guilds\n" f"* Connected to {len(self.client.guilds)} guilds\n"
f"```" f"```",
reference=message if self.answer else None,
mention_author=self.answer_mention,
) )
async def help(self, _client: discord.client, message: discord.Message, *args: str): async def help(self, _client: discord.client, message: discord.Message, *args: str):
if len(args) <= 1: if len(args) <= 1:
tmp_alias = '' if self.alias is None else self.alias tmp_alias = "" if self.alias is None else self.alias
await message.channel.send( await message.channel.send(
"```\n" "```\n"
"List of available commands:\n" "List of available commands:\n"
+ "".join([f"* {tmp_alias}{command.help_short}\n" for command in self.__commands]) + "".join(
+ "```" [
f"* {tmp_alias}{command.help_short}\n"
for command in self.__commands
]
)
+ "```",
reference=message if self.answer else None,
mention_author=self.answer_mention,
) )
else: else:
for command in self.__commands: for command in self.__commands:
if re.match(command.regex, args[1].lower() if self.lower_command_names else args[1]): if re.match(
command.regex,
args[1].lower() if self.lower_command_names else args[1],
):
await message.channel.send(command.help_long) await message.channel.send(command.help_long)
return return
await message.channel.send(f"Command `{sanitize_input(args[1])}` not found") await message.channel.send(
f"Command `{sanitize_input(args[1])}` not found",
reference=message if self.answer else None,
mention_author=self.answer_mention,
)
async def on_ready(self): async def on_ready(self):
# Change status # Change status
logging.info(f"{self.client.user} (v{self.version}) has connected to {len(self.client.guilds)} Discord guilds") logging.info(
if self.guild_logs_file is not None and not os.path.exists(self.guild_logs_file): f"{self.client.user} (v{self.version}) has connected to {len(self.client.guilds)} Discord guilds"
)
if self.guild_logs_file is not None and not os.path.exists(
self.guild_logs_file
):
for guild in self.client.guilds: for guild in self.client.guilds:
await self.on_guild_join(guild) await self.on_guild_join(guild)
while True: while True:
await self.client.change_presence( await self.client.change_presence(
activity=discord.Game(self.__generate_game()), activity=discord.Game(self.__generate_game()),
status=discord.Status.online status=discord.Status.online,
) )
await asyncio.sleep(self.game_change_delay) await asyncio.sleep(self.game_change_delay)
@@ -140,13 +167,18 @@ class Bot(object):
is_direct = message.channel.type == discord.ChannelType.private is_direct = message.channel.type == discord.ChannelType.private
is_mention = self.any_mention and self.client.user in message.mentions \ is_mention = (
self.any_mention
and self.client.user in message.mentions
or bool(re.match(f"^<@!?{self.client.user.id}>", message.content)) or bool(re.match(f"^<@!?{self.client.user.id}>", message.content))
)
if self.remove_mentions: if self.remove_mentions:
message.content = re.sub(r"<@!?[^>]+>", "", message.content) message.content = re.sub(r"<@!?[^>]+>", "", message.content)
elif is_mention: elif is_mention:
message.content = re.sub(f"^<@!?{self.client.user.id}>", "", message.content) message.content = re.sub(
f"^<@!?{self.client.user.id}>", "", message.content
)
command_args = parse_arguments(message.content) command_args = parse_arguments(message.content)
@@ -165,7 +197,12 @@ class Bot(object):
command_found = False command_found = False
for command in self.__commands: for command in self.__commands:
if re.match(command.regex, command_args[0].lower() if self.lower_command_names else command_args[0]): if re.match(
command.regex,
command_args[0].lower()
if self.lower_command_names
else command_args[0],
):
if self.log_calls: if self.log_calls:
debug(message, str(command_args)) debug(message, str(command_args))
@@ -175,7 +212,7 @@ class Bot(object):
if not permissions.send_messages: if not permissions.send_messages:
await message.author.create_dm() await message.author.create_dm()
await message.author.dm_channel.send( await message.author.dm_channel.send(
f"Hi, this bot doesn\'t have the permission to send a message to" f"Hi, this bot doesn't have the permission to send a message to"
f" #{message.channel} in server '{message.guild}'" f" #{message.channel} in server '{message.guild}'"
) )
return return
@@ -196,7 +233,9 @@ class Bot(object):
with open(self.guild_logs_file, encoding="utf-8", mode="a") as f: with open(self.guild_logs_file, encoding="utf-8", mode="a") as f:
f.write(f"{datetime.now():%Y-%m-%d %H:%M} -{guild.id}: {guild.name}\n") f.write(f"{datetime.now():%Y-%m-%d %H:%M} -{guild.id}: {guild.name}\n")
def register_command(self, regex: str, compute: CommandFunction, help_short: str, help_long: str): def register_command(
self, regex: str, compute: CommandFunction, help_short: str, help_long: str
):
if not regex.startswith("^"): if not regex.startswith("^"):
regex = "^" + regex regex = "^" + regex
if not regex.endswith("$"): if not regex.endswith("$"):
@@ -216,9 +255,13 @@ class Bot(object):
self.__token = os.getenv(self.token_env_var) self.__token = os.getenv(self.token_env_var)
if self.__token is None: if self.__token is None:
if path.exists(env_file) and env_file_found: if path.exists(env_file) and env_file_found:
raise EnvironmentError(f"No token was loaded, please verify your .env file has '{self.token_env_var}'") raise EnvironmentError(
f"No token was loaded, please verify your .env file has '{self.token_env_var}'"
)
else: else:
raise EnvironmentError(f"No environment variable '{self.token_env_var}' found") raise EnvironmentError(
f"No environment variable '{self.token_env_var}' found"
)
self.__t0 = datetime.now() self.__t0 = datetime.now()
# Launch client and rerun on errors # Launch client and rerun on errors
while True: while True:
@@ -231,7 +274,7 @@ class Bot(object):
if repr(e) != self.__last_error: if repr(e) != self.__last_error:
self.__last_error = repr(e) self.__last_error = repr(e)
filename = f"error_{t:%Y-%m-%d_%H-%M-%S}.txt" filename = f"error_{t:%Y-%m-%d_%H-%M-%S}.txt"
with open(filename, 'w') as f: with open(filename, "w") as f:
f.write( f.write(
f"{self.app_name} v{self.version} started at {self.__t0:%Y-%m-%d %H:%M}\r\n" f"{self.app_name} v{self.version} started at {self.__t0:%Y-%m-%d %H:%M}\r\n"
f"Exception raised at {t:%Y-%m-%d %H:%M}\r\n" f"Exception raised at {t:%Y-%m-%d %H:%M}\r\n"
+1 -1
View File
@@ -1,2 +1,2 @@
discord discord.py
python-dotenv python-dotenv
+2 -2
View File
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
setuptools.setup( setuptools.setup(
name="miniscord-Klemek", name="miniscord-Klemek",
version="0.0.1", version="0.0.2",
author="Klemek", author="Klemek",
description="A minimalist discord bot API", description="A minimalist discord bot API",
long_description=long_description, long_description=long_description,
@@ -17,5 +17,5 @@ setuptools.setup(
"License :: OSI Approved :: GNU License", "License :: OSI Approved :: GNU License",
"Operating System :: OS Independent", "Operating System :: OS Independent",
], ],
python_requires='>=3.6', python_requires=">=3.6",
) )