diff --git a/src/api/client.py b/src/api/client.py index 29ecf49..c80e3f3 100644 --- a/src/api/client.py +++ b/src/api/client.py @@ -16,9 +16,12 @@ from __future__ import annotations import src.misc -from typing import Union +from src.exceptions import TagNotFound +from bs4 import BeautifulSoup +from typing import Union, TYPE_CHECKING, Optional from collections import OrderedDict -from typing import TYPE_CHECKING, Optional +from functools import cache +from urllib.parse import urlparse, urlunparse if TYPE_CHECKING: from src.wiki import Wiki @@ -29,13 +32,9 @@ class Client: """ def __init__(self, wiki): self.__recent_changes: Wiki = wiki - self.WIKI_API_PATH: str = src.misc.WIKI_API_PATH - self.WIKI_ARTICLE_PATH: str = src.misc.WIKI_ARTICLE_PATH - self.WIKI_SCRIPT_PATH: str = src.misc.WIKI_SCRIPT_PATH - self.WIKI_JUST_DOMAIN: str = src.misc.WIKI_JUST_DOMAIN self.content_parser = src.misc.ContentParser - self.tags = self.__recent_changes.tags self.LinkParser: type(src.misc.LinkParser) = src.misc.LinkParser + self.last_request: Optional[dict] = None #self.make_api_request: src.rc.wiki.__recent_changes.api_request = self.__recent_changes.api_request @property @@ -46,6 +45,37 @@ class Client: else: return dict() + @cache + def tag(self, tag_name: str): + for tag in self.last_request["tags"]: + if tag["name"] == tag_name: + try: + return (BeautifulSoup(tag["displayname"], "lxml")).get_text() + except KeyError: + return None # Tags with no display name are hidden and should not appear on RC as well + raise TagNotFound + + @property + def WIKI_API_PATH(self): + return self.__recent_changes.script_url + "api.php" + + @property + def WIKI_SCRIPT_PATH(self): + return self.__recent_changes.script_url + + @property + def WIKI_JUST_DOMAIN(self): + parsed_url = urlparse(self.__recent_changes.script_url) + return urlunparse((*parsed_url[0:2], "", "", "", "")) + + @property + def WIKI_ARTICLE_PATH(self): + parsed_url = urlparse(self.__recent_changes.script_url) + try: + return urlunparse((*parsed_url[0:2], "", "", "", "")) + self.last_request["query"]["general"]["articlepath"] + except KeyError: + return urlunparse((*parsed_url[0:2], "", "", "", "")) + "wiki/" + def parse_links(self, summary: str): link_parser = self.LinkParser() link_parser.feed(summary) diff --git a/src/api/context.py b/src/api/context.py index 1c88d5a..cdea133 100644 --- a/src/api/context.py +++ b/src/api/context.py @@ -14,6 +14,7 @@ # along with RcGcDb. If not, see . from __future__ import annotations from typing import TYPE_CHECKING +from collections import namedtuple if TYPE_CHECKING: from src.api.client import Client @@ -21,10 +22,11 @@ if TYPE_CHECKING: class Context: """Context object containing client and some metadata regarding specific formatter call""" - def __init__(self, message_type: str, webhook_url: str, client: Client): + def __init__(self, display_options: namedtuple("Settings", ["lang", "display"]), webhook_url: list, client: Client): self.client = client self.webhook_url = webhook_url - self.message_type = message_type + self.display_options = display_options + self.message_type = display_options.display self.categories = None self.parsedcomment = None self.event = None diff --git a/src/api/util.py b/src/api/util.py index ec3bd8f..06999d9 100644 --- a/src/api/util.py +++ b/src/api/util.py @@ -17,7 +17,7 @@ import re from urllib.parse import quote from typing import Optional, Callable, TYPE_CHECKING -from src.exceptions import ServerError, MediaWikiError +from src.exceptions import ServerError, MediaWikiError, TagNotFound from src.discord.message import DiscordMessage from src.configloader import settings import src.misc @@ -148,16 +148,17 @@ def embed_helper(ctx: Context, message: DiscordMessage, change: dict, set_user=T if settings["appearance"]["embed"]["show_footer"]: message["timestamp"] = change["timestamp"] if "tags" in change and change["tags"]: - tag_displayname = [] + tags_displayname = [] for tag in change["tags"]: - if tag in ctx.client.tags: - if ctx.client.tags[tag] is None: + try: + tag_display = ctx.client.tag(tag) + if tag_display is None: continue # Ignore hidden tags else: - tag_displayname.append(ctx.client.tags[tag]) - else: - tag_displayname.append(tag) - message.add_field(formatters_i18n.pgettext("recent changes Tags", "Tags"), ", ".join(tag_displayname)) + tags_displayname.append(tag_display) + except TagNotFound: + tags_displayname.append(tag) + message.add_field(formatters_i18n.pgettext("recent changes Tags", "Tags"), ", ".join(tags_displayname)) if ctx.categories is not None and not (len(ctx.categories["new"]) == 0 and len(ctx.categories["removed"]) == 0): new_cat = (_("**Added**: ") + ", ".join(list(ctx.categories["new"])[0:16]) + ( "\n" if len(ctx.categories["new"]) <= 15 else _(" and {} more\n").format( diff --git a/src/exceptions.py b/src/exceptions.py index 02f16da..69d83b1 100644 --- a/src/exceptions.py +++ b/src/exceptions.py @@ -25,6 +25,9 @@ class ListFull(Exception): class EmbedListFull(Exception): pass +class TagNotFound(Exception): + pass + class ServerError(Exception): """Exception for when a request fails because of Server error""" pass diff --git a/src/wiki.py b/src/wiki.py index 4c14f2d..d52c1da 100644 --- a/src/wiki.py +++ b/src/wiki.py @@ -14,6 +14,7 @@ from src.formatters.rc import embed_formatter, compact_formatter from src.formatters.discussions import feeds_embed_formatter, feeds_compact_formatter from src.api.hooks import formatter_hooks from src.api.client import Client +from src.api.context import Context from src.misc import parse_link from src.i18n import langs from src.wiki_ratelimiter import RateLimiter @@ -186,6 +187,7 @@ class Wiki: while True: # Trap event in case there are more changes needed to be fetched try: request = await self.fetch_wiki(amount=amount) + self.client.last_request = request except WikiServerError: return # TODO Add a log entry? else: @@ -248,8 +250,7 @@ async def rc_processor(wiki: Wiki, change: dict, changed_categories: dict, displ metadata = src.discord.DiscordMessageMetadata("POST", rev_id=change.get("revid", None), log_id=change.get("logid", None), page_id=change.get("pageid", None)) context = Context(display_options, webhooks, wiki.client) - if ("actionhidden" in change or "suppressed" in change) and "suppressed" not in settings[ - "ignored"]: # if event is hidden using suppression + if ("actionhidden" in change or "suppressed" in change) and "suppressed" not in settings["ignored"]: # if event is hidden using suppression context.event = "suppressed" try: discord_message: Optional[src.discord.DiscordMessage] = default_message("suppressed", display_options.display, formatter_hooks)(context, change)