From d0795c76e777d89ea08cbab50a9dab5e6a535a34 Mon Sep 17 00:00:00 2001 From: Frisk Date: Wed, 28 Apr 2021 13:37:32 +0200 Subject: [PATCH] More work on all things! --- extensions/base/mediawiki.py | 56 ++++++++++++++---------------- src/api/client.py | 2 ++ src/api/util.py | 67 ++++++++++++++++++++++++++++++++++-- src/discord/message.py | 2 ++ src/discussion_formatters.py | 4 +-- src/wiki.py | 3 +- 6 files changed, 98 insertions(+), 36 deletions(-) diff --git a/extensions/base/mediawiki.py b/extensions/base/mediawiki.py index 2b39ab6..6148f81 100644 --- a/extensions/base/mediawiki.py +++ b/extensions/base/mediawiki.py @@ -19,7 +19,7 @@ from src.discord.message import DiscordMessage from src.api import formatter from src.i18n import rc_formatters from src.api.context import Context -from src.api.util import embed_helper +from src.api.util import embed_helper, sanitize_to_url, parse_mediawiki_changes, clean_link, compact_author from src.configloader import settings from src.exceptions import * @@ -44,20 +44,29 @@ def embed_edit(ctx: Context, change: dict) -> DiscordMessage: embed["color"] = 8750469 if change["title"].startswith("MediaWiki:Tag-"): # Refresh tag list when tag display name is edited ctx.client.refresh_internal_data() - embed["link"] = "{wiki}index.php?title={article}&curid={pageid}&diff={diff}&oldid={oldrev}".format( - wiki=ctx.client.WIKI_SCRIPT_PATH, pageid=change["pageid"], diff=change["revid"], oldrev=change["old_revid"], - article=change["title"].replace(" ", "_").replace("%", "%25").replace("\\", "%5C").replace("&", "%26")) + # Sparse is better than dense. + # Readability counts. + embed["url"] = "{wiki}index.php?title={article}&curid={pageid}&diff={diff}&oldid={oldrev}".format( + wiki=ctx.client.WIKI_SCRIPT_PATH, + pageid=change["pageid"], + diff=change["revid"], + oldrev=change["old_revid"], + article=sanitize_to_url(change["title"]) + ) embed["title"] = "{redirect}{article} ({new}{minor}{bot}{space}{editsize})".format( - redirect="⤷ " if "redirect" in change else "", article=change["title"], editsize="+" + str( - editsize) if editsize > 0 else editsize, new=_("(N!) ") if action == "new" else "", - minor=_("m") if action == "edit" and "minor" in change else "", bot=_('b') if "bot" in change else "", + redirect="⤷ " if "redirect" in change else "", + article=change["title"], + editsize="+" + str(editsize) if editsize > 0 else editsize, + new=_("(N!) ") if action == "new" else "", + minor=_("m") if action == "edit" and "minor" in change else "", + bot=_('b') if "bot" in change else "", space=" " if "bot" in change or (action == "edit" and "minor" in change) or action == "new" else "") if settings["appearance"]["embed"]["show_edit_changes"]: try: if action == "new": changed_content = ctx.client.make_api_request( - "?action=compare&format=json&torev={diff}&topst=1&prop=diff".format(diff=change["revid"] - ), "compare", "*") + "?action=compare&format=json&fromslots=main&torev={diff}&fromtext-main=&topst=1&prop=diff".format( + diff=change["revid"]), "compare", "*") else: changed_content = ctx.client.make_api_request( "?action=compare&format=json&fromrev={oldrev}&torev={diff}&topst=1&prop=diff".format( @@ -65,34 +74,21 @@ def embed_edit(ctx: Context, change: dict) -> DiscordMessage: except ServerError: changed_content = None if changed_content: - EditDiff = ctx.client.content_parser() - EditDiff.feed(changed_content) - if EditDiff.small_prev_del: - if EditDiff.small_prev_del.replace("~~", "").isspace(): - EditDiff.small_prev_del = _('__Only whitespace__') - else: - EditDiff.small_prev_del = EditDiff.small_prev_del.replace("~~~~", "") - if EditDiff.small_prev_ins: - if EditDiff.small_prev_ins.replace("**", "").isspace(): - EditDiff.small_prev_ins = _('__Only whitespace__') - else: - EditDiff.small_prev_ins = EditDiff.small_prev_ins.replace("****", "") - logger.debug("Changed content: {}".format(EditDiff.small_prev_ins)) - if EditDiff.small_prev_del and not action == "new": - embed.add_field(_("Removed"), "{data}".format(data=EditDiff.small_prev_del), inline=True) - if EditDiff.small_prev_ins: - embed.add_field(_("Added"), "{data}".format(data=EditDiff.small_prev_ins), inline=True) + parse_mediawiki_changes(ctx, changed_content, embed) else: logger.warning("Unable to download data on the edit content!") + embed["description"] = ctx.parsedcomment return embed @formatter.compact(event="edit", mode="compact") def compact_edit(ctx: Context, change: dict): + parsed_comment = "" if ctx.parsedcomment is None else " *(" + ctx.parsedcomment + ")*" + author, author_url = compact_author(ctx, change) action = ctx.event - edit_link = link_formatter("{wiki}index.php?title={article}&curid={pageid}&diff={diff}&oldid={oldrev}".format( + edit_link = clean_link("{wiki}index.php?title={article}&curid={pageid}&diff={diff}&oldid={oldrev}".format( wiki=ctx.client.WIKI_SCRIPT_PATH, pageid=change["pageid"], diff=change["revid"], oldrev=change["old_revid"], - article=change["title"])) + article=sanitize_to_url(change["title"]))) logger.debug(edit_link) edit_size = change["newlen"] - change["oldlen"] sign = "" @@ -101,8 +97,6 @@ def compact_edit(ctx: Context, change: dict): bold = "" if abs(edit_size) > 500: bold = "**" - if change["title"].startswith("MediaWiki:Tag-"): - pass if action == "edit": content = _( "[{author}]({author_url}) edited [{article}]({edit_link}){comment} {bold}({sign}{edit_size}){bold}").format( @@ -116,7 +110,7 @@ def compact_edit(ctx: Context, change: dict): return DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url, content=content) -# Page creation - event new +# Page creation - event new aliases to embed_edit since they share a lot of their code @formatter.embed(event="new", mode="embed") def embed_new(ctx, change): diff --git a/src/api/client.py b/src/api/client.py index ddacaf4..30ab395 100644 --- a/src/api/client.py +++ b/src/api/client.py @@ -36,6 +36,7 @@ class Client: self.WIKI_SCRIPT_PATH = src.misc.WIKI_SCRIPT_PATH self.WIKI_JUST_DOMAIN = src.misc.WIKI_JUST_DOMAIN self.content_parser = src.misc.ContentParser + self.tags = self.__recent_changes.tags #self.make_api_request: src.rc.wiki.__recent_changes.api_request = self.__recent_changes.api_request def refresh_internal_data(self): @@ -68,6 +69,7 @@ class Client: def get_formatters(self): return self._formatters + def get_ipmapper(self) -> dict: """Returns a dict mapping IPs with amount of their edits""" return self.__recent_changes.map_ips \ No newline at end of file diff --git a/src/api/util.py b/src/api/util.py index 5529017..9d95ee0 100644 --- a/src/api/util.py +++ b/src/api/util.py @@ -20,6 +20,9 @@ from src.discord.message import DiscordMessage from src.configloader import settings import src.misc import logging +from src.i18n import rc_formatters + +_ = rc_formatters.gettext if TYPE_CHECKING: from src.api.context import Context @@ -31,9 +34,39 @@ def default_message(event: str, formatter_hooks: dict) -> Callable: return formatter_hooks.get(event, formatter_hooks.get("generic", formatter_hooks["no_formatter"])) -def link_formatter(link: str) -> str: +def clean_link(link: str) -> str: + """Adds <> around the link to prevent its embedding""" + return "<" + link.replace(" ", "_") + ">" + + +def sanitize_to_markdown(text: str): + """Sanitizes given text to """ + + +def sanitize_to_url(text: str) -> str: # TODO ) replaces needed? """Formats a link to not embed it""" - return "<" + quote(link.replace(" ", "_"), "/:?=&") + ">" + return quote(text, " \\/:").replace(' ', "_") + + +def parse_mediawiki_changes(ctx: Context, content: str, embed: DiscordMessage) -> None: + """Parses MediaWiki changes and adds them to embed as fields "Added" and "Removed" """ + edit_diff = ctx.client.content_parser() + edit_diff.feed(content) + if edit_diff.small_prev_del: + if edit_diff.small_prev_del.replace("~~", "").isspace(): + edit_diff.small_prev_del = _('__Only whitespace__') + else: + edit_diff.small_prev_del = edit_diff.small_prev_del.replace("~~~~", "") + if edit_diff.small_prev_ins: + if edit_diff.small_prev_ins.replace("**", "").isspace(): + edit_diff.small_prev_ins = _('__Only whitespace__') + else: + edit_diff.small_prev_ins = edit_diff.small_prev_ins.replace("****", "") + logger.debug("Changed content: {}".format(edit_diff.small_prev_ins)) + if edit_diff.small_prev_del and not ctx.event == "new": + embed.add_field(_("Removed"), "{data}".format(data=edit_diff.small_prev_del), inline=True) + if edit_diff.small_prev_ins: + embed.add_field(_("Added"), "{data}".format(data=edit_diff.small_prev_ins), inline=True) def escape_formatting(data: str) -> str: @@ -46,6 +79,19 @@ def create_article_path(article: str) -> str: return src.misc.WIKI_ARTICLE_PATH.replace("$1", article) +def compact_author(ctx: Context, change: dict) -> (Optional[str], Optional[str]): + """Returns link to the author and the author itself respecting the settings""" + author, author_url = None, None + if ctx.event != "suppressed": + author_url = clean_link(create_article_path("User:{user}".format(user=change["user"]))) # TODO Sanitize user in here and in embed_helper + if "anon" in change: + change["user"] = _("Unregistered user") + author = change["user"] + else: + author = change["user"] + return author, author_url + + def embed_helper(ctx: Context, message: DiscordMessage, change: dict) -> None: """Helps in preparing common edit/log fields for events. Passed arguments automatically become saturated with needed data. @@ -84,4 +130,21 @@ def embed_helper(ctx: Context, message: DiscordMessage, change: dict) -> None: amount=ip_mapper[change["user"]]) else: author_url = create_article_path("User:{}".format(change["user"].replace(" ", "_"))) + if settings["appearance"]["embed"]["show_footer"]: + message["timestamp"] = change["timestamp"] + if "tags" in change and change["tags"]: + tag_displayname = [] + for tag in change["tags"]: + if tag in ctx.client.tags: + if ctx.client.tags[tag] is None: + continue # Ignore hidden tags + else: + tag_displayname.append(ctx.client.tags[tag]) + else: + tag_displayname.append(tag) + message.add_field(_("Tags"), ", ".join(tag_displayname)) + if ctx.categories is not None and not (len(ctx.categories["new"]) == 0 and len(ctx.categorie["removed"]) == 0): + new_cat = (_("**Added**: ") + ", ".join(list(ctx.categories["new"])[0:16]) + ("\n" if len(ctx.categories["new"])<=15 else _(" and {} more\n").format(len(ctx.categories["new"])-15))) if ctx.categories["new"] else "" + del_cat = (_("**Removed**: ") + ", ".join(list(ctx.categories["removed"])[0:16]) + ("" if len(ctx.categories["removed"])<=15 else _(" and {} more").format(len(ctx.categories["removed"])-15))) if ctx.categories["removed"] else "" + message.add_field(_("Changed categories"), new_cat + del_cat) message.set_author(change["user"], author_url) diff --git a/src/discord/message.py b/src/discord/message.py index fab107c..ceab2a5 100644 --- a/src/discord/message.py +++ b/src/discord/message.py @@ -72,6 +72,8 @@ class DiscordMessage: self.embed["color"] = math.floor(self.embed["color"]) if not self.embed["author"]["icon_url"] and settings["event_appearance"].get(self.event_type, {"icon": None})["icon"]: self.embed["author"]["icon_url"] = settings["event_appearance"][self.event_type]["icon"] + if len(self.embed["title"]) > 254: + self.embed["title"] = self.embed["title"][0:253] + "…" def set_author(self, name, url, icon_url=""): self.embed["author"]["name"] = name diff --git a/src/discussion_formatters.py b/src/discussion_formatters.py index af292d2..61c86de 100644 --- a/src/discussion_formatters.py +++ b/src/discussion_formatters.py @@ -19,7 +19,7 @@ import gettext from urllib.parse import quote_plus from src.configloader import settings -from src.api.util import link_formatter, escape_formatting, create_article_path +from src.api.util import escape_formatting, create_article_path, clean_link from src.discord.queue import send_to_discord from src.discord.message import DiscordMessage, DiscordMessageMetadata from src.i18n import discussion_formatters @@ -44,7 +44,7 @@ def compact_formatter(post_type, post, article_paths): else: if post["createdBy"]["name"]: author = post["createdBy"]["name"] - author_url = link_formatter(create_article_path("User:{user}".format(user=author))) + author_url = clean_link(create_article_path("User:{user}".format(user=author))) else: author_url = "<{url}f/u/{creatorId}>".format(url=settings["fandom_discussions"]["wiki_url"], creatorId=post["creatorId"]) event_type = "discussion" diff --git a/src/wiki.py b/src/wiki.py index cae969c..cf9ce03 100644 --- a/src/wiki.py +++ b/src/wiki.py @@ -304,8 +304,9 @@ class Wiki(object): # Making request try: if isinstance(params, str): # Todo Make it so there are some default arguments like warning/error format appended - request = self.session.get(WIKI_API_PATH + params, timeout=timeout, allow_redirects=allow_redirects) + request = self.session.get(WIKI_API_PATH + params+"&errorformat=raw", timeout=timeout, allow_redirects=allow_redirects) elif isinstance(params, OrderedDict): + params["errorformat"] = "raw" request = self.session.get(WIKI_API_PATH, params=params, timeout=timeout, allow_redirects=allow_redirects) else: raise BadRequest(params)