diff options
author | 2022-09-30 21:53:26 +0300 | |
---|---|---|
committer | 2022-09-30 21:53:26 +0300 | |
commit | c813e3fae3502920d62d2b4ca6d65d894cca939b (patch) | |
tree | 861c15e742e005427e8c3613b96901256ded070a | |
parent | Filter adding commands, simplify infraction (diff) |
Add filter edit command
-rw-r--r-- | bot/exts/filtering/filtering.py | 135 |
1 files changed, 116 insertions, 19 deletions
diff --git a/bot/exts/filtering/filtering.py b/bot/exts/filtering/filtering.py index 7ffa121e1..8ff26795e 100644 --- a/bot/exts/filtering/filtering.py +++ b/bot/exts/filtering/filtering.py @@ -2,7 +2,7 @@ import json import operator import re from collections import defaultdict -from functools import reduce +from functools import partial, reduce from typing import Literal, Optional, get_type_hints from discord import Colour, Embed, HTTPException, Message @@ -269,23 +269,7 @@ class Filtering(Cog): return filter_, filter_list, list_type = result - # Get filter list settings - default_setting_values = {} - for type_ in ("actions", "validations"): - for _, setting in filter_list.defaults[list_type][type_].items(): - default_setting_values.update(to_serializable(setting.dict())) - - # Get the filter's overridden settings - overrides_values = {} - for settings in (filter_.actions, filter_.validations): - if settings: - for _, setting in settings.items(): - overrides_values.update(to_serializable(setting.dict())) - - if filter_.extra_fields_type: - extra_fields_overrides = filter_.extra_fields.dict(exclude_unset=True) - else: - extra_fields_overrides = {} + overrides_values, extra_fields_overrides = self._filter_overrides(filter_) all_settings_repr_dict = build_filter_repr_dict( filter_list, list_type, type(filter_), overrides_values, extra_fields_overrides @@ -361,6 +345,76 @@ class Filtering(Cog): list_type, filter_list = result await self._add_filter(ctx, noui, list_type, filter_list, content, description_and_settings) + @filter.command(name="edit", aliases=("e",)) + async def f_edit( + self, + ctx: Context, + noui: Optional[Literal["noui"]], + filter_id: int, + *, + description_and_settings: Optional[str] = None + ) -> None: + """ + Edit a filter specified by its ID. + + Unless `noui` is specified, a UI will be provided to edit the content, description, and settings + before confirmation. + + The settings can be provided in the command itself, in the format of `setting_name=value` (no spaces around the + equal sign). The value doesn't need to (shouldn't) be surrounded in quotes even if it contains spaces. + + To edit the filter's content, use the UI. + """ + result = self._get_filter_by_id(filter_id) + if result is None: + await ctx.send(f":x: Could not find a filter with ID `{filter_id}`.") + return + filter_, filter_list, list_type = result + filter_type = type(filter_) + settings, filter_settings = self._filter_overrides(filter_) + description, new_settings, new_filter_settings = description_and_settings_converter( + filter_list.name, self.loaded_settings, self.loaded_filter_settings, description_and_settings + ) + + content = filter_.content + description = description or filter_.description + settings.update(new_settings) + filter_settings.update(new_filter_settings) + patch_func = partial(self._patch_filter, filter_id) + + if noui: + await patch_func( + ctx.message, filter_list, list_type, filter_type, content, description, settings, filter_settings + ) + + else: + embed = Embed(colour=Colour.blue()) + embed.description = f"`{filter_.content}`" + if description: + embed.description += f" - {description}" + embed.set_author( + name=f"Filter #{filter_id} - {past_tense(list_type.name.lower())} {filter_list.name}".title()) + embed.set_footer(text=( + "Field names with an asterisk have values which override the defaults of the containing filter list. " + f"To view all defaults of the list, run `!filterlist describe {list_type.name} {filter_list.name}`." + )) + + view = filters_ui.SettingsEditView( + filter_list, + list_type, + filter_type, + content, + description, + settings, + filter_settings, + self.loaded_settings, + self.loaded_filter_settings, + ctx.author, + embed, + patch_func + ) + await ctx.send(embed=embed, reference=ctx.message, view=view) + @filter.group(aliases=("settings",)) async def setting(self, ctx: Context) -> None: """Group for settings-related commands.""" @@ -553,6 +607,22 @@ class Filtering(Cog): if id_ in sublist: return sublist[id_], filter_list, list_type + @staticmethod + def _filter_overrides(filter_: Filter) -> tuple[dict, dict]: + """Get the filter's overrides to the filter list settings and the extra fields settings.""" + overrides_values = {} + for settings in (filter_.actions, filter_.validations): + if settings: + for _, setting in settings.items(): + overrides_values.update(to_serializable(setting.dict())) + + if filter_.extra_fields_type: + extra_fields_overrides = filter_.extra_fields.dict(exclude_unset=True) + else: + extra_fields_overrides = {} + + return overrides_values, extra_fields_overrides + async def _add_filter( self, ctx: Context, @@ -625,7 +695,34 @@ class Filtering(Cog): } response = await bot.instance.api_client.post('bot/filter/filters', json=payload) new_filter = filter_list.add_filter(response, list_type) - await msg.channel.send(f"✅ Added filter: {new_filter}", reference=msg) + await msg.reply(f"✅ Added filter: {new_filter}") + + @staticmethod + async def _patch_filter( + filter_id: int, + msg: Message, + filter_list: FilterList, + list_type: ListType, + filter_type: type[Filter], + content: str, + description: str | None, + settings: dict, + filter_settings: dict + ) -> None: + """PATCH the new data of the filter to the site API.""" + valid, error_msg = filter_type.validate_filter_settings(filter_settings) + if not valid: + raise BadArgument(f"Error while validating filter-specific settings: {error_msg}") + + list_id = filter_list.list_ids[list_type] + description = description or None + payload = { + "filter_list": list_id, "content": content, "description": description, + "additional_field": json.dumps(filter_settings), **settings + } + response = await bot.instance.api_client.patch(f'bot/filter/filters/{filter_id}', json=payload) + edited_filter = filter_list.add_filter(response, list_type) + await msg.reply(f"✅ Edited filter: {edited_filter}") # endregion |