From 394d78fb2c6364e969bc63033f9a50f17b81d4e5 Mon Sep 17 00:00:00 2001 From: Elnath Date: Sat, 26 Dec 2020 22:01:13 +0100 Subject: [PATCH] Implemented forget command --- VocalMaisBot.py | 100 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 24 deletions(-) diff --git a/VocalMaisBot.py b/VocalMaisBot.py index 01e0ff8..de672c9 100755 --- a/VocalMaisBot.py +++ b/VocalMaisBot.py @@ -4,7 +4,7 @@ import logging import sys from pathlib import Path import json -from typing import TextIO, Any, List, Dict +from typing import TextIO, Any, List, Dict, Union import textwrap import discord @@ -26,6 +26,25 @@ class VocalMaisBot(discord.Client): logger.critical(f"Impossible to parse watched channels file, JSON error: {e}") sys.exit(1) + @staticmethod + async def _check_administrator_for_command(message: discord.Message) -> bool: + if message.author.guild_permissions.administrator: + return True + else: + await message.channel.send(f":dragon_face: Only an administrator can control me!") + return False + + def write_watched_channels_file(self): + logger.debug("Writing watched channels information to file") + self.watched_channels_file.seek(0) + self.watched_channels_file.truncate() + json.dump(self.watched_channels, self.watched_channels_file, indent = 2) + self.watched_channels_file.flush() + logger.debug("Written watched channels information to file") + + async def sorry_do_not_understand(self, message: discord.Message): + await message.channel.send(f"Sorry I did not understand this message. Try `@{self.user.display_name} help` for help") + async def on_ready(self): logger.info("Connected and ready!") logger.debug(f"Logged as {self.user}") @@ -49,36 +68,30 @@ class VocalMaisBot(discord.Client): return await message.channel.send(":ping_pong:") elif _check_list_element(contents, 1, "register"): return await self.register_channel(message) + elif _check_list_element(contents, 1, "forget"): + return await self.forget_channel(message) elif _check_list_element(contents, 1, "list"): return await self.list_watched_channels(message) else: return self.sorry_do_not_understand(message) - async def sorry_do_not_understand(self, message: discord.Message): - await message.channel.send(f"Sorry I did not understand this message. Try `@{self.user.display_name} help` for help") - async def print_help(self, channel: discord.TextChannel): me = self.user.display_name message = f""" - **·** `@{me}register channel_id` : make me watch the voice channel with id `channel_id` - **·** `@{me} help` : print this help + **·** `@{me} register channel_id` : make me watch the voice channel with id `channel_id` + **·** `@{me} forget channel_id` : make me stop watching the voice channel with id `channel_id` **·** `@{me} list` : list watched channels + **·** `@{me} help` : print this help **·** `@{me} ping` : pong """ await channel.send(embed = discord.Embed(title = "Available commands", description = textwrap.dedent(message))) async def register_channel(self, message: discord.Message): - message_elements = message.content.split() - if len(message_elements) < 3: - return await self.sorry_do_not_understand(message) - channel_id = message_elements[2] - try: - channel_id = int(channel_id) - except ValueError: - return await message.channel.send(f":x: {channel_id} can not be converted to number") - - if not message.author.guild_permissions.administrator: - return await message.channel.send(f":dragon_face: Only an administrator can control me!") + channel_id = await self._get_channel_id_for_command(message) + if channel_id is None: + return + if not await self._check_administrator_for_command(message): + return # Retrieving the channel channel = self.get_channel(channel_id) @@ -101,13 +114,52 @@ class VocalMaisBot(discord.Client): self.loop.call_soon(self.write_watched_channels_file) return await message.channel.send(f":white_check_mark: I am now watching {channel.name}") - def write_watched_channels_file(self): - logger.debug("Writing watched channels information to file") - self.watched_channels_file.seek(0) - self.watched_channels_file.truncate() - json.dump(self.watched_channels, self.watched_channels_file, indent = 2) - self.watched_channels_file.flush() - logger.debug("Written watched channels information to file") + async def forget_channel(self, message: discord.Message): + channel_id = await self._get_channel_id_for_command(message) + if channel_id is None: + return + if not await self._check_administrator_for_command(message): + return + + did_something = False + guild_id = str(message.guild.id) + if guild_id in self.watched_channels: + guild_info = self.watched_channels[guild_id] + if "watched_channels" in guild_info: + watched_channels_ids = guild_info["watched_channels"] + try: + watched_channels_ids.remove(channel_id) + did_something = True + except ValueError: + pass # The channel already was not in the list + + # Getting the channel name (if it exists), for pretty printing + channel = self.get_channel(channel_id) + if channel is None: # Channel does not exist + channel_name = str(channel_id) + else: + channel_name = f"{channel.name} ({channel_id})" + + if did_something: + self.write_watched_channels_file() + await message.channel.send(f":white_check_mark: I am no longer watching {channel_name}") + else: + await message.channel.send(f":thumbsup: I already was not watching {channel_name}") + + async def _get_channel_id_for_command(self, message: discord.Message) -> Union[int, None]: + """ + Get the channel id from a command message in the form "@Bot command channel_id", or answer with an error message and return None if not possible. + """ + message_elements = message.content.split() + if len(message_elements) < 3: + await self.sorry_do_not_understand(message) + return None + channel_id = message_elements[2] + try: + return int(channel_id) + except ValueError: + await message.channel.send(f":x: {channel_id} can not be converted to number") + return None async def list_watched_channels(self, message: discord.Message): guild_id = str(message.guild.id)