From bd5706c0ce46b811ed67f4a69e8a120fcb22a17e Mon Sep 17 00:00:00 2001 From: Infinidoge Date: Wed, 1 Jan 2025 00:51:41 -0500 Subject: [PATCH] add basic import functionality --- nomen/settings.py | 71 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/nomen/settings.py b/nomen/settings.py index e22ea31..b86434c 100644 --- a/nomen/settings.py +++ b/nomen/settings.py @@ -1,14 +1,23 @@ +import json import logging from typing import Literal import disnake +import re2 as re from disnake.ext.commands import Cog, group, guild_only +from .notifications import KeywordError from .utils import confirm log = logging.getLogger("nomen.settings") log.setLevel(logging.DEBUG) +DUSTY_DATA_LINE = re.compile(r"^(.+) – notified (\d+) times$") + + +class InvalidImportFormat(Exception): + pass + class Settings(Cog): def __init__(self, bot): @@ -44,11 +53,57 @@ You may want to `{ctx.clean_prefix}nomen export` first""" else: await ctx.send("Cancelled.") + async def import_json(self, ctx, data): + try: + data = json.loads(data) + except json.JSONDecodeError as e: + raise InvalidImportFormat from e + await ctx.send("Importing JSON") + + async def import_dusty(self, ctx, data): + lines = map(str.strip, data.split("\n")) + to_add = [] + + for line in lines: + if match := DUSTY_DATA_LINE.fullmatch(line): + to_add.append((match.group(1), int(match.group(2)))) + else: + raise InvalidImportFormat + + await ctx.send(f"Importing from Dusty notification list to {ctx.guild}...") + + added = [] + errors = [] + + async with ctx.typing(): + notifications = self.bot.get_cog("Notifications") + for keyword, count in to_add: + try: + await notifications.add_keyword(ctx.guild.id, ctx.author.id, keyword, False, count) + added.append(keyword) + except KeywordError as e: + errors.append(e) + + if not errors: + await ctx.send("Successfully imported all keywords!") + else: + await ctx.send( + f"Import successful, with some errors\n\n" + f"Sucessfully imported:\n{"\n".join(f"- {keyword}" for keyword in added)}\n" + f"Errors (check PMs):\n{"\n".join(f"- {e.msg}" for e in errors)}\n\n" + f"If you want to import erroring keywords, delete conflicting keywords and modify the list to only include the ones that failed to import, and run the command again." + ) + for e in errors: + await ctx.author.send(e.dm_msg) + + async def import_raw(self, data): + pass + @nomen.command(name="import") @guild_only() - async def _import(self, ctx): + async def _import(self, ctx, *, data): """ - Imports a JSON of all of your user data + Imports user data, either from JSON or from a simple list """ schema = { "disabled": bool, @@ -65,6 +120,18 @@ You may want to `{ctx.clean_prefix}nomen export` first""" ], } + notifications = self.bot.get_cog("Notifications") + + try: + await self.import_json(ctx, data) + await ctx.send("Sorry, JSON imports and exports haven't been implemented yet.") + return + except InvalidImportFormat: + try: + await self.import_dusty(ctx, data) + except InvalidImportFormat: + await ctx.send("Invalid import format") + # @nomen.command() # @guild_only() # async def export(self, ctx):