diff --git a/extensions/base/mediawiki.py b/extensions/base/mediawiki.py index fcfa9af..db0362a 100644 --- a/extensions/base/mediawiki.py +++ b/extensions/base/mediawiki.py @@ -18,7 +18,8 @@ import math from src.discord.message import DiscordMessage from src.api import formatter from src.i18n import rc_formatters -from src.api.client import Client, client +from src.api.client import Client +from src.api.context import Context from src.configloader import settings from src.exceptions import * @@ -32,7 +33,7 @@ class base(): super().__init__(api) @formatter.embed(event="edit", mode="embed") - def embed_edit(self, ctx: Client, change: dict) -> DiscordMessage: + def embed_edit(self, ctx: Context, change: dict) -> DiscordMessage: embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) action = ctx.event editsize = change["newlen"] - change["oldlen"] @@ -92,6 +93,7 @@ class base(): embed.add_field(_("Added"), "{data}".format(data=EditDiff.small_prev_ins), inline=True) else: logger.warning("Unable to download data on the edit content!") + return embed @formatter.compact(event="edit", mode="embed") def compact_edit(self, change: dict): diff --git a/src/api/client.py b/src/api/client.py index 9f1ea6d..aa81346 100644 --- a/src/api/client.py +++ b/src/api/client.py @@ -60,5 +60,7 @@ class Client: """ return self.__recent_changes.api_request(params, *json_path, timeout, allow_redirects) + def get_formatters(self): + return self._formatters -client = Client() \ No newline at end of file +client = Client() diff --git a/src/api/context.py b/src/api/context.py new file mode 100644 index 0000000..f6e575d --- /dev/null +++ b/src/api/context.py @@ -0,0 +1,23 @@ +# This file is part of Recent changes Goat compatible Discord webhook (RcGcDw). +# +# RcGcDw is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# RcGcDw is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with RcGcDw. If not, see . + + +class Context: + """Context object containing client and some metadata regarding specific formatter call""" + def __init__(self, message_type: str, webhook_url: str, client): + self.client = client + self.webhook_url = webhook_url + self.message_type = message_type + self.event = None \ No newline at end of file diff --git a/src/api/formatter.py b/src/api/formatter.py index 72df39c..318a4f8 100644 --- a/src/api/formatter.py +++ b/src/api/formatter.py @@ -14,11 +14,13 @@ # along with RcGcDw. If not, see . import src.rcgcdw +import logging from src.configloader import settings from src.exceptions import FormatterBreaksAPISpec from src.discord.message import DiscordMessage from typing import Optional, Callable +logger = logging.getLogger("src.api.formatter") def _register_formatter(func: Callable[[dict], DiscordMessage], kwargs: dict[str, str], formatter_type: str, action_type: Optional[str]=None): @@ -35,6 +37,10 @@ def _register_formatter(func: Callable[[dict], DiscordMessage], kwargs: dict[str if action_type is None: raise FormatterBreaksAPISpec("event type") if settings["appearance"]["mode"] == formatter_type: + if action_type in src.rcgcdw.formatter_hooks: + logger.warning(f"Action {action_type} is already defined inside of " + f"{src.rcgcdw.formatter_hooks[action_type].__module__}! " + f"Overwriting it with one from {func.__module__}") src.rcgcdw.formatter_hooks[action_type] = func diff --git a/src/rc.py b/src/rc.py index 676ac86..f0c5a2f 100644 --- a/src/rc.py +++ b/src/rc.py @@ -20,6 +20,7 @@ import sys import time import logging import requests +import src.api.client from bs4 import BeautifulSoup from src.configloader import settings @@ -28,6 +29,7 @@ from src.misc import WIKI_SCRIPT_PATH, WIKI_API_PATH, datafile, send_simple, saf from src.discord.queue import messagequeue from src.exceptions import MWError, BadRequest, ClientError, ServerError, MediaWikiError from src.session import session +from src.api.context import Context from typing import Union # from src.rc_formatters import compact_formatter, embed_formatter, compact_abuselog_formatter, embed_abuselog_formatter from src.i18n import rc @@ -202,7 +204,7 @@ class Wiki(object): logger.debug("Change ({}) is lower or equal to recent_id {}".format(change["rcid"], recent_id)) continue logger.debug(recent_id) - essential_info(change, categorize_events.get(change.get("revid"), None)) + rc_processor(change, categorize_events.get(change.get("revid"), None)) return highest_id def prepare_abuse_log(self, abuse_log: list): @@ -454,12 +456,13 @@ class Wiki(object): wiki = Wiki() -def essential_info(change, changed_categories): +def rc_processor(change, changed_categories): """Prepares essential information for both embed and compact message format.""" + formatters = src.api.client.client.get_formatters() # TODO Make it better? Importing might be a hell logger.debug(change) + context = Context(settings["appearance"]["mode"], settings["webhookURL"], src.api.client.client) if ("actionhidden" in change or "suppressed" in change) and "suppressed" not in settings["ignored"]: # if event is hidden using suppression - appearance_mode("suppressed", change, "", changed_categories, wiki) - return + context.event = "suppressed" if "commenthidden" not in change: LinkParser.feed(change["parsedcomment"]) parsed_comment = LinkParser.new_string diff --git a/src/rcgcdw.py b/src/rcgcdw.py index 2a67041..0da7fdc 100644 --- a/src/rcgcdw.py +++ b/src/rcgcdw.py @@ -39,19 +39,22 @@ if settings["fandom_discussions"]["enabled"]: import src.discussions TESTING = True if "--test" in sys.argv else False # debug mode, pipeline testing - +formatter_hooks = {} # Prepare logging logging.config.dictConfig(settings["logging"]) logger = logging.getLogger("rcgcdw") logger.debug("Current settings: {settings}".format(settings=settings)) from src.migrations import * # migrations after logging -try: - import extensions -except ImportError: - logger.critical("No extensions module found. What's going on?") - raise - sys.exit(1) + + +def load_extensions(): + """Loads all of the extensions, can be a local import because all we need is them to register""" + try: + import extensions + except ImportError: + logger.critical("No extensions module found. What's going on?") + sys.exit(1) storage = datafile # Remove previous data holding file if exists and limitfetch allows @@ -63,8 +66,6 @@ if settings["limitrefetch"] != -1 and os.path.exists("lastchange.txt") is True: datafile.save_datafile() os.remove("lastchange.txt") -formatter_hooks = {} - def day_overview_request(): logger.info("Fetching daily overview... This may take up to 30 seconds!") @@ -251,6 +252,7 @@ if 1 == 2: # additional translation strings in unreachable code _("autoreview"), _("autopatrol"), _("wiki_guardian"), ngettext("second", "seconds", 1), ngettext("minute", "minutes", 1), ngettext("hour", "hours", 1), ngettext("day", "days", 1), ngettext("week", "weeks", 1), ngettext("month", "months",1), ngettext("year", "years", 1), ngettext("millennium", "millennia", 1), ngettext("decade", "decades", 1), ngettext("century", "centuries", 1)) # noinspection PyUnreachableCode +load_extensions() if TESTING: logger.debug("DEBUGGING ")