From 366a83aba16ac5e947d0b0d464b6bc7e868b9e85 Mon Sep 17 00:00:00 2001 From: Frisk Date: Tue, 13 Aug 2024 12:28:42 +0200 Subject: [PATCH] Synced formatters from rcgcdw, updated API function --- extensions/base/__init__.py | 2 + extensions/base/abusefilter.py | 132 +++++++++-- extensions/base/approvedrevs.py | 95 ++++++++ extensions/base/datadump.py | 4 +- extensions/base/discussions.py | 27 +-- extensions/base/mediawiki.py | 269 +++++++++++----------- extensions/base/templateclassification.py | 47 ++++ src/api/util.py | 8 +- 8 files changed, 404 insertions(+), 180 deletions(-) create mode 100644 extensions/base/approvedrevs.py create mode 100644 extensions/base/templateclassification.py diff --git a/extensions/base/__init__.py b/extensions/base/__init__.py index eb02987..2e87d3b 100644 --- a/extensions/base/__init__.py +++ b/extensions/base/__init__.py @@ -24,4 +24,6 @@ import extensions.base.discussions import extensions.base.curseprofile import extensions.base.interwiki import extensions.base.renameuser +import extensions.base.approvedrevs +import extensions.base.templateclassification import extensions.base.rcgcdb diff --git a/extensions/base/abusefilter.py b/extensions/base/abusefilter.py index edae5a1..a9201b3 100644 --- a/extensions/base/abusefilter.py +++ b/extensions/base/abusefilter.py @@ -15,14 +15,16 @@ import ipaddress import logging +import datetime from src.discord.message import DiscordMessage from src.api import formatter from src.api.context import Context -from src.api.util import embed_helper, sanitize_to_url, parse_mediawiki_changes, clean_link, compact_author, sanitize_to_markdown +from src.api.util import embed_helper, sanitize_to_url, clean_link, compact_author, \ + sanitize_to_markdown, compact_summary # Order results from most drastic first to less drastic last abuselog_results = ["degroup", "blockautopromote", "rangeblock", "block", "disallow", "throttle", "warn", "tag", ""] -abusefilter_results = lambda string, _, default: {"degroup": _("**Removed from privileged groups**"), "blockautopromote": _("Removed autoconfirmed group"), "rangeblock": _("**IP range blocked**"), "block": _("**Blocked user**"), "disallow": _("Disallowed the action"), "throttle": _("Throttled actions"), "warn": _("Warning issued"), "tag": _("Tagged the edit"), "": _("None")}.get(string, default) +abusefilter_results = lambda string, _, default: {"degroup": _("**Removed from privileged groups**"), "blockautopromote": _("**Removed autopromoted groups**"), "rangeblock": _("**IP range blocked**"), "block": _("**Blocked user**"), "disallow": _("Disallowed the action"), "throttle": _("Throttled actions"), "warn": _("Warning issued"), "tag": _("Tagged the edit"), "": _("None")}.get(string, default) abusefilter_actions = lambda string, _, default: {"edit": _("Edit"), "upload": _("Upload"), "move": _("Move"), "stashupload": _("Stash upload"), "delete": _("Deletion"), "createaccount": _("Account creation"), "autocreateaccount": _("Auto account creation")}.get(string, default) logger = logging.getLogger("extensions.base") @@ -40,16 +42,15 @@ def abuselog_action(results): return action -def abuse_filter_format_user(change, settings): - author = change["user"] - if settings.get("hide_ips", False): - try: - ipaddress.ip_address(change["user"]) - except ValueError: - pass - else: - author = _("Unregistered user") - return author +def abuse_filter_is_ip(change): + is_ip = False + try: + ipaddress.ip_address(change["user"]) + except ValueError: + pass + else: + is_ip = True + return is_ip @formatter.embed(event="abuselog") @@ -57,11 +58,13 @@ def embed_abuselog(ctx: Context, change: dict): results = change["result"].split(",") action = abuselog_action(results) embed = DiscordMessage(ctx.message_type, action, ctx.webhook_url) - author = abuse_filter_format_user(change, ctx.settings) - embed["title"] = ctx._("{user} triggered \"{abuse_filter}\"").format(user=author, abuse_filter=sanitize_to_markdown(change["filter"])) - embed.add_field(ctx._("Performed"), abusefilter_actions(change["action"], ctx._, change["action"])) - embed.add_field(ctx._("Title"), sanitize_to_markdown(change.get("title", ctx._("Unknown")))) - embed.add_field(ctx._("Action taken"), ctx._(", ").join([abusefilter_results(result, ctx._, result) for result in results])) + embed["title"] = sanitize_to_markdown(change["filter"]) + embed["url"] = ctx.client.create_article_path("Special:AbuseLog/{entry}".format(entry=change["id"])) + embed.add_field(ctx._("Title"), "[{target}]({target_url})".format(target=change.get("title", ctx._("Unknown")), + target_url=clean_link(ctx.client.create_article_path(sanitize_to_url(change.get("title", ctx._("Unknown")))))), inline=True) + embed.add_field(ctx._("Performed"), abusefilter_actions(change["action"], ctx._, change["action"]), inline=True) + embed.add_field(ctx._("Action taken"), "\n".join([abusefilter_results(result, ctx._, result) for result in results])) + embed_helper(ctx, embed, change, is_anon=abuse_filter_is_ip(change), set_desc=False) return embed @@ -69,10 +72,10 @@ def embed_abuselog(ctx: Context, change: dict): def compact_abuselog(ctx: Context, change: dict): results = change["result"].split(",") action = abuselog_action(results) - author_url = clean_link(ctx.client.create_article_path("User:{user}".format(user=change["user"]))) - author = abuse_filter_format_user(change, ctx.settings) - message = ctx._("[{author}]({author_url}) triggered *{abuse_filter}*, performing the action \"{action}\" on *[{target}]({target_url})* - action taken: {result}.").format( + author, author_url = compact_author(ctx, change, is_anon=abuse_filter_is_ip(change)) + message = ctx._("[{author}]({author_url}) triggered *[{abuse_filter}]({details_url})*, performing the action \"{action}\" on *[{target}]({target_url})* - action taken: {result}.").format( author=author, author_url=author_url, abuse_filter=sanitize_to_markdown(change["filter"]), + details_url=clean_link(ctx.client.create_article_path("Special:AbuseLog/{entry}".format(entry=change["id"]))), action=abusefilter_actions(change["action"], ctx._, change["action"]), target=change.get("title", ctx._("Unknown")), target_url=clean_link(ctx.client.create_article_path(sanitize_to_url(change.get("title", ctx._("Unknown"))))), result=ctx._(", ").join([abusefilter_results(result, ctx._, result) for result in results])) @@ -132,3 +135,92 @@ def compact_abuselog_create(ctx: Context, change: dict): 'newId'], filter_url=link) return DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url, content=content) + +# rights/blockautopromote - AbuseFilter filter block auto promote +def block_expiry(change: dict, ctx: Context) -> str: + if change["logparams"]["duration"] in ["infinite", "indefinite", "infinity", "never"]: + return ctx._("for infinity and beyond") + else: + if "expiry" in change["logparams"]: + expiry_date_time_obj = datetime.datetime.strptime(change["logparams"]["expiry"], '%Y-%m-%dT%H:%M:%SZ') + timestamp_date_time_obj = datetime.datetime.strptime(change["timestamp"], '%Y-%m-%dT%H:%M:%SZ') + timedelta_for_expiry = (expiry_date_time_obj - timestamp_date_time_obj).total_seconds() + elif isinstance(change["logparams"]["duration"], int): + timedelta_for_expiry = change["logparams"]["duration"] + else: + return change["logparams"]["duration"] # Temporary? Should be rare? We will see in testing + years, days, hours, minutes = timedelta_for_expiry // 31557600, timedelta_for_expiry % 31557600 // 86400, \ + timedelta_for_expiry % 86400 // 3600, timedelta_for_expiry % 3600 // 60 + if not any([years, days, hours, minutes]): + return ctx._("for less than a minute") + time_names = ( + ctx.ngettext("year", "years", years), ctx.ngettext("day", "days", days), ctx.ngettext("hour", "hours", hours), + ctx.ngettext("minute", "minutes", minutes)) + final_time = [] + for num, timev in enumerate([years, days, hours, minutes]): + if timev: + final_time.append( + ctx._("for {time_number} {time_unit}").format(time_unit=time_names[num], time_number=int(timev))) + return ctx._(", ").join(final_time) + + +@formatter.embed(event="rights/blockautopromote", mode="embed") +def embed_rights_blockautopromote(ctx, change): + embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) + user = change["title"].split(':', 1)[1] + try: + ipaddress.ip_address(user) + embed["url"] = ctx.client.create_article_path("Special:Contributions/{user}".format(user=user)) + except ValueError: + embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) + embed["title"] = ctx._("Blocked autopromotion of {user} {time}").format(user=user, time=block_expiry(change, ctx)) + embed_helper(ctx, embed, change) + return embed + + +@formatter.compact(event="rights/blockautopromote", mode="compact") +def compact_rights_blockautopromote(ctx, change): + user = change["title"].split(':', 1)[1] + restriction_description = "" + author, author_url = compact_author(ctx, change) + parsed_comment = compact_summary(ctx) + try: + ipaddress.ip_address(user) + link = clean_link(ctx.client.create_article_path("Special:Contributions/{user}".format(user=user))) + except ValueError: + link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) + content = ctx._( + "[{author}]({author_url}) blocked the autopromotion of [{user}]({user_url}) {time}{comment}").format(author=author, + author_url=author_url, + user=sanitize_to_markdown(user), + time=block_expiry( + change, ctx), + user_url=link, + comment=parsed_comment) + return DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url, content=content) + + +# rights/restoreautopromote - AbuseFilter filter restore auto promote + +@formatter.embed(event="rights/restoreautopromote", mode="embed") +def embed_rights_restoreautopromote(ctx, change): + embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) + embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) + user = change["title"].split(':', 1)[1] + embed["title"] = ctx._("Restored autopromotion of {user}").format(user=sanitize_to_markdown(user)) + embed_helper(ctx, embed, change) + return embed + + +@formatter.compact(event="rights/restoreautopromote") +def compact_rights_restoreautopromote(ctx, change): + author, author_url = compact_author(ctx, change) + link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) + user = change["title"].split(':', 1)[1] + parsed_comment = compact_summary(ctx) + content = ctx._("[{author}]({author_url}) restored the autopromotion capability of [{user}]({user_url}){comment}").format(author=author, + author_url=author_url, + user=sanitize_to_markdown(user), + user_url=link, + comment=parsed_comment) + return DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url, content=content) diff --git a/extensions/base/approvedrevs.py b/extensions/base/approvedrevs.py new file mode 100644 index 0000000..6462da1 --- /dev/null +++ b/extensions/base/approvedrevs.py @@ -0,0 +1,95 @@ +# 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 . + +from src.discord.message import DiscordMessage +from src.api import formatter +from src.api.context import Context +from src.api.util import embed_helper, compact_author, sanitize_to_markdown, sanitize_to_url, clean_link +from src.misc import LinkParser + +# Approved Revs - https://mediawiki.org/wiki/Extension:Approved_Revs +# approval/approvefile + + +@formatter.embed(event="approval/approvefile") +def embed_approval_approvefile(ctx: Context, change: dict): + embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) + embed_helper(ctx, embed, change) + embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) + embed["title"] = ctx._("Approved a file revision of {file}").format(file=sanitize_to_markdown(change["title"])) + link_parser_object = LinkParser(ctx.client.WIKI_JUST_DOMAIN) + link_parser_object.feed(change.get("logparams", {}).get("0", "")) + embed["description"] = ctx._("File version from {time} got approved").format(name=change["title"], time=link_parser_object.new_string) + # TODO Make timestamp more user friendly? Getting user who uploaded will be a pain though, same with approval/approve + return embed + + +@formatter.compact(event="approval/approvefile") +def compact_approval_approvefile(ctx: Context, change: dict): + author, author_url = compact_author(ctx, change) + link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) + content = ctx._("[{author}]({author_url}) approved a file revision of [{file_name}]({file_url})").format(author=author, + author_url=author_url, + file_name=sanitize_to_markdown(change[ + "title"]), + file_url=link) + return DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url, content=content) + + +# approval/approve +@formatter.embed(event="approval/approve") +def embed_approval_approve(ctx: Context, change: dict): + embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) + embed_helper(ctx, embed, change) + embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) + embed["title"] = ctx._("Approved a revision of {article}").format(article=sanitize_to_markdown(change["title"])) + link_parser_object = LinkParser(ctx.client.WIKI_JUST_DOMAIN) + link_parser_object.feed(change.get("logparams", {}).get("0", "")) + embed["description"] = ctx._("Revision number {revision_id} got approved").format(name=change["title"], time=link_parser_object.new_string) + return embed + + +@formatter.compact(event="approval/approve") +def compact_approval_approve(ctx: Context, change: dict): + author, author_url = compact_author(ctx, change) + link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) + content = ctx._("[{author}]({author_url}) approved a revision of [{article}]({article_url})").format(author=author, + author_url=author_url, + article=sanitize_to_markdown(change[ + "title"]), + article_url=link) + return DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url, content=content) + + +# approval/unapprove +@formatter.embed(event="approval/unapprove") +def embed_approval_approve(ctx: Context, change: dict): + embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) + embed_helper(ctx, embed, change) + embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) + embed["title"] = ctx._("Unapproved revision of {article}").format(article=sanitize_to_markdown(change["title"])) + return embed + + +@formatter.compact(event="approval/unapprove") +def compact_approval_approve(ctx: Context, change: dict): + author, author_url = compact_author(ctx, change) + link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) + content = ctx._("[{author}]({author_url}) unapproved a revision of [{article}]({article_url})").format(author=author, + author_url=author_url, + article=sanitize_to_markdown(change[ + "title"]), + article_url=link) + return DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url, content=content) diff --git a/extensions/base/datadump.py b/extensions/base/datadump.py index 6b30b37..7874db3 100644 --- a/extensions/base/datadump.py +++ b/extensions/base/datadump.py @@ -34,7 +34,7 @@ def embed_datadump_generate(ctx: Context, change: dict) -> DiscordMessage: return embed -@formatter.compact(event="mdatadump/generate") +@formatter.compact(event="datadump/generate") def compact_datadump_generate(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) parsed_comment = compact_summary(ctx) @@ -56,7 +56,7 @@ def embed_datadump_delete(ctx: Context, change: dict) -> DiscordMessage: return embed -@formatter.compact(event="mdatadump/delete") +@formatter.compact(event="datadump/delete") def compact_datadump_delete(ctx: Context, change: dict) -> DiscordMessage: author, author_url = compact_author(ctx, change) parsed_comment = compact_summary(ctx) diff --git a/extensions/base/discussions.py b/extensions/base/discussions.py index ece878b..243fd2a 100644 --- a/extensions/base/discussions.py +++ b/extensions/base/discussions.py @@ -23,6 +23,7 @@ from src.api.context import Context from src.discord.message import DiscordMessage, DiscordMessageMetadata from src.api import formatter + logger = logging.getLogger("rcgcdw.discussion_formatter") @@ -61,8 +62,7 @@ class DiscussionsFromHellParser: suf=suffix) else: if ctype == "code_block": - self.markdown_text += item[ - "text"] # ignore formatting on preformatted text which cannot have additional formatting anyways + self.markdown_text += item["text"] # ignore formatting on preformatted text which cannot have additional formatting anyways else: self.markdown_text += sanitize_to_markdown(item["text"]) elif item["type"] == "paragraph": @@ -77,8 +77,8 @@ class DiscussionsFromHellParser: logger.debug(item["attrs"]["id"]) if item["attrs"]["id"] is not None: self.markdown_text = "{old}{img_url}\n".format(old=self.markdown_text, img_url= - self.post["_embedded"]["contentImages"][int(item["attrs"]["id"])]["url"]) - self.image_last = self.post["_embedded"]["contentImages"][int(item["attrs"]["id"])]["url"] + self.post["_embedded"]["contentImages"][int(item["attrs"]["id"])]["url"]) + self.image_last = self.post["_embedded"]["contentImages"][int(item["attrs"]["id"])]["url"] except (IndexError, ValueError, TypeError): logger.warning("Image {} not found.".format(item["attrs"]["id"])) logger.debug(self.markdown_text) @@ -132,7 +132,6 @@ def common_discussions(post: dict, embed: DiscordMessage, ctx: Context): embed["timestamp"] = datetime.datetime.fromtimestamp(post["creationDate"]["epochSecond"], tz=datetime.timezone.utc).isoformat() - # discussion/forum - Discussions on the "forum" available via "Discuss" button @formatter.embed(event="discussion/forum") @@ -144,7 +143,7 @@ def embed_discussion_forum(ctx: Context, post: dict): author = post["createdBy"]["name"] embed.set_author(author, "{url}f/u/{creatorId}".format(url=ctx.client.WIKI_SCRIPT_PATH, creatorId=post["creatorId"]), - icon_url=post["createdBy"]["avatarUrl"]) + icon_url=post["createdBy"]["avatarUrl"]) if not post["isReply"]: embed["url"] = "{url}f/p/{threadId}".format(url=ctx.client.WIKI_SCRIPT_PATH, threadId=post["threadId"]) @@ -181,13 +180,10 @@ def embed_discussion_forum(ctx: Context, post: dict): if post["_embedded"]["thread"][0]["tags"]: tag_displayname = [] for tag in post["_embedded"]["thread"][0]["tags"]: - tag_displayname.append( - "[{title}]({url})".format(title=tag["articleTitle"], url=ctx.client.create_article_path( - quote_plus(tag["articleTitle"].replace(" ", "_"), "/:?=&")))) + tag_displayname.append("[{title}]({url})".format(title=tag["articleTitle"], url=ctx.client.create_article_path( + quote_plus(tag["articleTitle"].replace(" ", "_"), "/:?=&")))) if len(", ".join(tag_displayname)) > 1000: - embed.add_field(ctx.pgettext("Fandom discussions Tags/Forums", "Tags"), - ctx.pgettext("Fandom discussions amount of Tags/Forums", "{} tags").format( - len(post["_embedded"]["thread"][0]["tags"]))) + embed.add_field(ctx.pgettext("Fandom discussions Tags/Forums", "Tags"), ctx.pgettext("Fandom discussions amount of Tags/Forums", "{} tags").format(len(post["_embedded"]["thread"][0]["tags"]))) else: embed.add_field(ctx.pgettext("Fandom discussions Tags/Forums", "Tags"), ", ".join(tag_displayname)) else: @@ -234,7 +230,6 @@ def compact_discussion_forum(ctx: Context, post: dict): forumName=post["forumName"]) return DiscordMessage("compact", event_type, ctx.webhook_url, content=message) - # discussion/wall - Wall posts/replies @@ -251,7 +246,7 @@ def compact_author_discussions(post: dict, ctx: Context): author_url = clean_link(ctx.client.create_article_path("User:{user}".format(user=author))) else: author_url = "<{url}f/u/{creatorId}>".format(url=ctx.client.WIKI_SCRIPT_PATH, - creatorId=post["creatorId"]) + creatorId=post["creatorId"]) return author, author_url @@ -287,8 +282,7 @@ def embed_discussion_wall(ctx: Context, post: dict): embed["url"] = "{url}wiki/Message_Wall:{user_wall}?threadId={threadId}".format( url=ctx.client.WIKI_SCRIPT_PATH, user_wall=quote_plus(user_wall.replace(" ", "_")), threadId=post["threadId"]) - embed["title"] = ctx._("Created \"{title}\" on {user}'s Message Wall").format(title=post["title"], - user=user_wall) + embed["title"] = ctx._("Created \"{title}\" on {user}'s Message Wall").format(title=post["title"], user=user_wall) else: embed.event_type = "discussion/wall/reply" embed["url"] = "{url}wiki/Message_Wall:{user_wall}?threadId={threadId}#{replyId}".format( @@ -320,7 +314,6 @@ def compact_discussion_wall(ctx: Context, post: dict): user_wall=quote_plus(user_wall.replace(" ", "_")), threadId=post["threadId"], replyId=post["id"]) return DiscordMessage("compact", event_type, ctx.webhook_url, content=message) - # discussion/article_comment - Article comments diff --git a/extensions/base/mediawiki.py b/extensions/base/mediawiki.py index 8b038de..096cfa6 100644 --- a/extensions/base/mediawiki.py +++ b/extensions/base/mediawiki.py @@ -118,7 +118,7 @@ def compact_edit(ctx: Context, change: dict) -> DiscordMessage: # Upload - upload/reupload, upload/upload @formatter.embed(event="upload/upload", mode="embed", aliases=["upload/overwrite", "upload/revert"]) -def embed_upload_upload(ctx, change) -> DiscordMessage: +def embed_upload_upload(ctx: Context, change: dict) -> DiscordMessage: license = None embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) action = ctx.event @@ -163,7 +163,8 @@ def embed_upload_upload(ctx, change) -> DiscordMessage: for num, revision in enumerate(urls): if revision["timestamp"] == change["logparams"][ "img_timestamp"]: # find the correct revision corresponding for this log entry - image_direct_url = "{rev}?{cache}".format(rev=revision["url"], + image_direct_url = "{rev}{c}rcgcdb={cache}".format(rev=revision["url"], + c="&" if "?" in revision["url"] else "?", cache=int(time.time() * 5)) # cachebusting break except KeyError: @@ -226,7 +227,7 @@ def embed_upload_upload(ctx, change) -> DiscordMessage: @formatter.compact(event="upload/revert", mode="compact") -def compact_upload_revert(ctx, change) -> DiscordMessage: +def compact_upload_revert(ctx: Context, change: dict) -> DiscordMessage: author, author_url = compact_author(ctx, change) file_link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) parsed_comment = compact_summary(ctx) @@ -237,7 +238,7 @@ def compact_upload_revert(ctx, change) -> DiscordMessage: @formatter.compact(event="upload/overwrite", mode="compact") -def compact_upload_overwrite(ctx, change) -> DiscordMessage: +def compact_upload_overwrite(ctx: Context, change: dict) -> DiscordMessage: author, author_url = compact_author(ctx, change) file_link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) parsed_comment = compact_summary(ctx) @@ -248,7 +249,7 @@ def compact_upload_overwrite(ctx, change) -> DiscordMessage: @formatter.compact(event="upload/upload", mode="compact") -def compact_upload_upload(ctx, change) -> DiscordMessage: +def compact_upload_upload(ctx: Context, change: dict) -> DiscordMessage: author, author_url = compact_author(ctx, change) file_link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) parsed_comment = compact_summary(ctx) @@ -263,7 +264,7 @@ def compact_upload_upload(ctx, change) -> DiscordMessage: # delete/delete - Page deletion @formatter.embed(event="delete/delete", mode="embed") -def embed_delete_delete(ctx, change) -> DiscordMessage: +def embed_delete_delete(ctx: Context, change: dict) -> DiscordMessage: embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed['url'] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -272,7 +273,7 @@ def embed_delete_delete(ctx, change) -> DiscordMessage: @formatter.compact(event="delete/delete", mode="compact") -def compact_delete_delete(ctx, change) -> DiscordMessage: +def compact_delete_delete(ctx: Context, change: dict) -> DiscordMessage: parsed_comment = compact_summary(ctx) author, author_url = compact_author(ctx, change) page_link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) @@ -287,7 +288,7 @@ def compact_delete_delete(ctx, change) -> DiscordMessage: # delete/delete_redir - Redirect deletion @formatter.embed(event="delete/delete_redir", mode="embed") -def embed_delete_delete_redir(ctx, change) -> DiscordMessage: +def embed_delete_delete_redir(ctx: Context, change: dict) -> DiscordMessage: embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed['url'] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -297,7 +298,7 @@ def embed_delete_delete_redir(ctx, change) -> DiscordMessage: @formatter.compact(event="delete/delete_redir", mode="compact") -def compact_delete_delete_redir(ctx, change) -> DiscordMessage: +def compact_delete_delete_redir(ctx: Context, change: dict) -> DiscordMessage: page_link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) author, author_url = compact_author(ctx, change) parsed_comment = compact_summary(ctx) @@ -311,7 +312,7 @@ def compact_delete_delete_redir(ctx, change) -> DiscordMessage: @formatter.embed(event="delete/restore", mode="embed") -def embed_delete_restore(ctx, change) -> DiscordMessage: +def embed_delete_restore(ctx: Context, change: dict) -> DiscordMessage: embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed['url'] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -320,7 +321,7 @@ def embed_delete_restore(ctx, change) -> DiscordMessage: @formatter.compact(event="delete/restore", mode="compact") -def compact_delete_restore(ctx, change) -> DiscordMessage: +def compact_delete_restore(ctx: Context, change: dict) -> DiscordMessage: page_link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) author, author_url = compact_author(ctx, change) parsed_comment = compact_summary(ctx) @@ -337,7 +338,7 @@ def compact_delete_restore(ctx, change) -> DiscordMessage: @formatter.embed(event="delete/event", mode="embed") -def embed_delete_event(ctx, change) -> DiscordMessage: +def embed_delete_event(ctx: Context, change: dict) -> DiscordMessage: embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed['url'] = ctx.client.create_article_path("Special:RecentChanges") @@ -346,7 +347,7 @@ def embed_delete_event(ctx, change) -> DiscordMessage: @formatter.compact(event="delete/event", mode="compact") -def compact_delete_event(ctx, change) -> DiscordMessage: +def compact_delete_event(ctx: Context, change: dict) -> DiscordMessage: author, author_url = compact_author(ctx, change) parsed_comment = compact_summary(ctx) content = ctx._("[{author}]({author_url}) changed visibility of log events{comment}").format(author=author, @@ -358,7 +359,7 @@ def compact_delete_event(ctx, change) -> DiscordMessage: # delete/revision - Deleting revision information @formatter.embed(event="delete/revision", mode="embed") -def embed_delete_revision(ctx, change) -> DiscordMessage: +def embed_delete_revision(ctx: Context, change: dict) -> DiscordMessage: embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) amount = len(change["logparams"]["ids"]) @@ -370,7 +371,7 @@ def embed_delete_revision(ctx, change) -> DiscordMessage: @formatter.compact(event="delete/revision", mode="compact") -def compact_delete_revision(ctx, change) -> DiscordMessage: +def compact_delete_revision(ctx: Context, change: dict) -> DiscordMessage: author, author_url = compact_author(ctx, change) amount = len(change["logparams"]["ids"]) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) @@ -387,7 +388,7 @@ def compact_delete_revision(ctx, change) -> DiscordMessage: @formatter.embed(event="move/move", mode="embed") -def embed_move_move(ctx, change) -> DiscordMessage: +def embed_move_move(ctx: Context, change: dict) -> DiscordMessage: embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change, set_desc=False) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["logparams"]['target_title'])) @@ -402,7 +403,7 @@ def embed_move_move(ctx, change) -> DiscordMessage: @formatter.compact(event="move/move", mode="compact") -def compact_move_move(ctx, change) -> DiscordMessage: +def compact_move_move(ctx: Context, change: dict) -> DiscordMessage: author, author_url = compact_author(ctx, change) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["logparams"]['target_title']))) redirect_status = ctx._("without making a redirect") if "suppressredirect" in change["logparams"] else ctx._( @@ -420,7 +421,7 @@ def compact_move_move(ctx, change) -> DiscordMessage: @formatter.embed(event="move/move_redir", mode="embed") -def embed_move_move_redir(ctx, change) -> DiscordMessage: +def embed_move_move_redir(ctx: Context, change: dict) -> DiscordMessage: embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change, set_desc=False) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["logparams"]['target_title'])) @@ -434,7 +435,7 @@ def embed_move_move_redir(ctx, change) -> DiscordMessage: @formatter.compact(event="move/move_redir", mode="compact") -def compact_move_move_redir(ctx, change) -> DiscordMessage: +def compact_move_move_redir(ctx: Context, change: dict) -> DiscordMessage: author, author_url = compact_author(ctx, change) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["logparams"]['target_title']))) redirect_status = ctx._("without making a redirect") if "suppressredirect" in change["logparams"] else ctx._( @@ -453,7 +454,7 @@ def compact_move_move_redir(ctx, change) -> DiscordMessage: @formatter.embed(event="protect/move_prot", mode="embed") -def embed_protect_move_prot(ctx, change): +def embed_protect_move_prot(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["logparams"]["oldtitle_title"])) @@ -465,7 +466,7 @@ def embed_protect_move_prot(ctx, change): @formatter.compact(event="protect/move_prot", mode="compact") -def compact_protect_move_prot(ctx, change): +def compact_protect_move_prot(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["logparams"]["oldtitle_title"]))) parsed_comment = compact_summary(ctx) @@ -481,7 +482,7 @@ def compact_protect_move_prot(ctx, change): @formatter.embed(event="protect/protect", mode="embed") -def embed_protect_protect(ctx, change): +def embed_protect_protect(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change, set_desc=False) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -494,7 +495,7 @@ def embed_protect_protect(ctx, change): @formatter.compact(event="protect/protect", mode="compact") -def compact_protect_protect(ctx, change): +def compact_protect_protect(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) parsed_comment = compact_summary(ctx) @@ -512,7 +513,7 @@ def compact_protect_protect(ctx, change): @formatter.embed(event="protect/modify", mode="embed") -def embed_protect_modify(ctx, change): +def embed_protect_modify(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change, set_desc=False) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -525,7 +526,7 @@ def embed_protect_modify(ctx, change): @formatter.compact(event="protect/modify", mode="compact") -def compact_protect_modify(ctx, change): +def compact_protect_modify(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) parsed_comment = compact_summary(ctx) @@ -543,7 +544,7 @@ def compact_protect_modify(ctx, change): @formatter.embed(event="protect/unprotect", mode="embed") -def embed_protect_unprotect(ctx, change): +def embed_protect_unprotect(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -552,7 +553,7 @@ def embed_protect_unprotect(ctx, change): @formatter.compact(event="protect/unprotect", mode="compact") -def compact_protect_unprotect(ctx, change): +def compact_protect_unprotect(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) parsed_comment = compact_summary(ctx) @@ -571,25 +572,27 @@ def block_expiry(change: dict, ctx: Context) -> str: expiry_date_time_obj = datetime.datetime.strptime(change["logparams"]["expiry"], '%Y-%m-%dT%H:%M:%SZ') timestamp_date_time_obj = datetime.datetime.strptime(change["timestamp"], '%Y-%m-%dT%H:%M:%SZ') timedelta_for_expiry = (expiry_date_time_obj - timestamp_date_time_obj).total_seconds() - years, days, hours, minutes = timedelta_for_expiry // 31557600, timedelta_for_expiry % 31557600 // 86400, \ - timedelta_for_expiry % 86400 // 3600, timedelta_for_expiry % 3600 // 60 - if not any([years, days, hours, minutes]): - return ctx._("for less than a minute") - time_names = ( - ctx.ngettext("year", "years", years), ctx.ngettext("day", "days", days), ctx.ngettext("hour", "hours", hours), - ctx.ngettext("minute", "minutes", minutes)) - final_time = [] - for num, timev in enumerate([years, days, hours, minutes]): - if timev: - final_time.append( - ctx._("for {time_number} {time_unit}").format(time_unit=time_names[num], time_number=int(timev))) - return ", ".join(final_time) + elif isinstance(change["logparams"]["duration"], int): + timedelta_for_expiry = change["logparams"]["duration"] else: return change["logparams"]["duration"] # Temporary? Should be rare? We will see in testing + years, days, hours, minutes = timedelta_for_expiry // 31557600, timedelta_for_expiry % 31557600 // 86400, \ + timedelta_for_expiry % 86400 // 3600, timedelta_for_expiry % 3600 // 60 + if not any([years, days, hours, minutes]): + return ctx._("for less than a minute") + time_names = ( + ctx.ngettext("year", "years", years), ctx.ngettext("day", "days", days), ctx.ngettext("hour", "hours", hours), + ctx.ngettext("minute", "minutes", minutes)) + final_time = [] + for num, timev in enumerate([years, days, hours, minutes]): + if timev: + final_time.append( + ctx._("for {time_number} {time_unit}").format(time_unit=time_names[num], time_number=int(timev))) + return ctx._(", ").join(final_time) @formatter.embed(event="block/block", mode="embed") -def embed_block_block(ctx, change): +def embed_block_block(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) user = change["title"].split(':', 1)[1] try: @@ -612,7 +615,9 @@ def embed_block_block(ctx, change): else: restriction_description = ctx._("Blocked from editing pages on following namespaces: ") for namespace in change["logparams"]["restrictions"]["namespaces"]: - if str(namespace) in ctx.client.namespaces: # if we have cached namespace name for given namespace number, add its name to the list + if str(namespace) == "0": + namespaces.append("*{ns}*".format(ns=ctx._("(Main)"))) + elif str(namespace) in ctx.client.namespaces: # if we have cached namespace name for given namespace number, add its name to the list namespaces.append("*{ns}*".format(ns=ctx.client.namespaces[str(namespace)]["*"])) else: namespaces.append("*{ns}*".format(ns=namespace)) @@ -632,7 +637,7 @@ def embed_block_block(ctx, change): @formatter.compact(event="block/block", mode="compact") -def compact_block_block(ctx, change): +def compact_block_block(ctx: Context, change: dict): user = change["title"].split(':', 1)[1] restriction_description = "" author, author_url = compact_author(ctx, change) @@ -642,35 +647,36 @@ def compact_block_block(ctx, change): link = clean_link(ctx.client.create_article_path("Special:Contributions/{user}".format(user=user))) except ValueError: link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) - else: - if "sitewide" not in change["logparams"]: - if "restrictions" in change["logparams"]: - if "pages" in change["logparams"]["restrictions"] and change["logparams"]["restrictions"]["pages"]: - restriction_description = ctx._(" on pages: ") - restricted_pages = ["*{page}*".format(page=i["page_title"]) for i in - change["logparams"]["restrictions"]["pages"]] - restriction_description = restriction_description + ", ".join(restricted_pages) - if "namespaces" in change["logparams"]["restrictions"] and change["logparams"]["restrictions"][ - "namespaces"]: - namespaces = [] - if restriction_description: - restriction_description = restriction_description + ctx._(" and namespaces: ") + if "sitewide" not in change["logparams"]: + if "restrictions" in change["logparams"]: + if "pages" in change["logparams"]["restrictions"] and change["logparams"]["restrictions"]["pages"]: + restriction_description = ctx._(" on pages: ") + restricted_pages = ["*{page}*".format(page=i["page_title"]) for i in + change["logparams"]["restrictions"]["pages"]] + restriction_description = restriction_description + ", ".join(restricted_pages) + if "namespaces" in change["logparams"]["restrictions"] and change["logparams"]["restrictions"][ + "namespaces"]: + namespaces = [] + if restriction_description: + restriction_description = restriction_description + ctx._(" and namespaces: ") + else: + restriction_description = ctx._(" on namespaces: ") + for namespace in change["logparams"]["restrictions"]["namespaces"]: + if str(namespace) == "0": + namespaces.append("*{ns}*".format(ns=ctx._("(Main)"))) + elif str(namespace) in ctx.client.namespaces: # if we have cached namespace name for given namespace number, add its name to the list + namespaces.append("*{ns}*".format(ns=ctx.client.namespaces[str(namespace)]["*"])) else: - restriction_description = ctx._(" on namespaces: ") - for namespace in change["logparams"]["restrictions"]["namespaces"]: - if str(namespace) in ctx.client.namespaces: # if we have cached namespace name for given namespace number, add its name to the list - namespaces.append("*{ns}*".format(ns=ctx.client.namespaces[str(namespace)]["*"])) - else: - namespaces.append("*{ns}*".format(ns=namespace)) - restriction_description = restriction_description + ", ".join(namespaces) - restriction_description = restriction_description + "." - if len(restriction_description) > 1020: - logger.debug(restriction_description) - restriction_description = restriction_description[:1020] + "…" + namespaces.append("*{ns}*".format(ns=namespace)) + restriction_description = restriction_description + ", ".join(namespaces) + restriction_description = restriction_description + "." + if len(restriction_description) > 1020: + logger.debug(restriction_description) + restriction_description = restriction_description[:1020] + "…" content = ctx._( "[{author}]({author_url}) blocked [{user}]({user_url}) {time}{restriction_desc}{comment}").format(author=author, author_url=author_url, - user=user, + user=sanitize_to_markdown(user), time=block_expiry( change, ctx), user_url=link, @@ -681,7 +687,7 @@ def compact_block_block(ctx, change): # block/reblock - Changing settings of a block @formatter.embed(event="block/reblock", mode="embed") -def embed_block_reblock(ctx, change): +def embed_block_reblock(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -691,7 +697,7 @@ def embed_block_reblock(ctx, change): @formatter.compact(event="block/reblock") -def compact_block_reblock(ctx, change): +def compact_block_reblock(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) user = change["title"].split(':', 1)[1] @@ -704,7 +710,7 @@ def compact_block_reblock(ctx, change): # block/unblock - Unblocking an user @formatter.embed(event="block/unblock", mode="embed") -def embed_block_unblock(ctx, change): +def embed_block_unblock(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -714,7 +720,7 @@ def embed_block_unblock(ctx, change): @formatter.compact(event="block/unblock") -def compact_block_unblock(ctx, change): +def compact_block_unblock(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) user = change["title"].split(':', 1)[1] @@ -732,7 +738,7 @@ def compact_block_unblock(ctx, change): @formatter.embed(event="suppressed", mode="embed") -def embed_suppressed(ctx, change): +def embed_suppressed(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed["url"] = ctx.client.create_article_path("") embed["title"] = ctx._("Action has been hidden by administration") @@ -741,7 +747,7 @@ def embed_suppressed(ctx, change): @formatter.compact(event="suppressed", mode="compact") -def compact_suppressed(ctx, change): +def compact_suppressed(ctx: Context, change: dict): content = ctx._("An action has been hidden by administration.") return DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url, content=content) @@ -749,7 +755,7 @@ def compact_suppressed(ctx, change): # import/upload - Importing pages by uploading exported XML files @formatter.embed(event="import/upload", mode="embed") -def embed_import_upload(ctx, change): +def embed_import_upload(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -760,7 +766,7 @@ def embed_import_upload(ctx, change): @formatter.compact(event="import/upload", mode="compact") -def compact_import_upload(ctx, change): +def compact_import_upload(ctx: Context, change: dict): link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) author, author_url = compact_author(ctx, change) parsed_comment = compact_summary(ctx) @@ -776,32 +782,40 @@ def compact_import_upload(ctx, change): @formatter.embed(event="import/interwiki", mode="embed") -def embed_import_interwiki(ctx, change): +def embed_import_interwiki(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) - embed["title"] = ctx.ngettext("Imported {article} with {count} revision from \"{source}\"", - "Imported {article} with {count} revisions from \"{source}\"", - change["logparams"]["count"]).format( - article=sanitize_to_markdown(change["title"]), count=change["logparams"]["count"], - source=sanitize_to_markdown(change["logparams"]["interwiki_title"])) + if "count" in change["logparams"] and "interwiki_title" in change["logparams"]: + embed["title"] = ctx.ngettext("Imported {article} with {count} revision from \"{source}\"", + "Imported {article} with {count} revisions from \"{source}\"", + change["logparams"]["count"]).format( + article=sanitize_to_markdown(change["title"]), count=change["logparams"]["count"], + source=sanitize_to_markdown(change["logparams"]["interwiki_title"])) + else: + embed["title"] = ctx._("Imported {article}").format(article=sanitize_to_markdown(change["title"])) return embed @formatter.compact(event="import/interwiki", mode="compact") -def compact_import_interwiki(ctx, change): +def compact_import_interwiki(ctx: Context, change: dict): link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) author, author_url = compact_author(ctx, change) - source_link = clean_link(ctx.client.create_article_path(change["logparams"]["interwiki_title"])) parsed_comment = compact_summary(ctx) - content = ctx.ngettext( - "[{author}]({author_url}) imported [{article}]({article_url}) with {count} revision from [{source}]({source_url}){comment}", - "[{author}]({author_url}) imported [{article}]({article_url}) with {count} revisions from [{source}]({source_url}){comment}", - change["logparams"]["count"]).format( - author=author, author_url=author_url, article=sanitize_to_markdown(change["title"]), article_url=link, - count=change["logparams"]["count"], source=sanitize_to_markdown(change["logparams"]["interwiki_title"]), - source_url=source_link, - comment=parsed_comment) + if "count" in change["logparams"] and "interwiki_title" in change["logparams"]: + source_link = clean_link(ctx.client.create_article_path(change["logparams"]["interwiki_title"])) + content = ctx.ngettext( + "[{author}]({author_url}) imported [{article}]({article_url}) with {count} revision from [{source}]({source_url}){comment}", + "[{author}]({author_url}) imported [{article}]({article_url}) with {count} revisions from [{source}]({source_url}){comment}", + change["logparams"]["count"]).format( + author=author, author_url=author_url, article=sanitize_to_markdown(change["title"]), article_url=link, + count=change["logparams"]["count"], source=sanitize_to_markdown(change["logparams"]["interwiki_title"]), + source_url=source_link, + comment=parsed_comment) + else: + content = ctx._("[{author}]({author_url}) imported [{article}]({article_url}){comment}").format( + author=author, author_url=author_url, article=sanitize_to_markdown(change["title"]), article_url=link, + comment=parsed_comment) return DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url, content=content) @@ -823,7 +837,7 @@ def get_changed_groups(change: dict, ctx: Context) -> [[str], [str]]: @formatter.embed(event="rights/rights", aliases=["rights/autopromote"]) -def embed_rights_rights(ctx, change): +def embed_rights_rights(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed["url"] = ctx.client.create_article_path(sanitize_to_url("User:{}".format(change["title"].split(":")[1]))) if ctx.event == "rights/rights": @@ -844,7 +858,7 @@ def embed_rights_rights(ctx, change): @formatter.compact(event="rights/rights", aliases=["rights/autopromote"]) -def compact_rights_rights(ctx, change): +def compact_rights_rights(ctx: Context, change: dict): link = clean_link(ctx.client.create_article_path(sanitize_to_url("User:{user}".format(user=change["title"].split(":")[1])))) added, removed = get_changed_groups(change, ctx) author, author_url = compact_author(ctx, change) @@ -871,7 +885,7 @@ def compact_rights_rights(ctx, change): # merge/merge - Merging histories of two pages @formatter.embed(event="merge/merge", mode="embed") -def embed_merge_merge(ctx, change): +def embed_merge_merge(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -883,7 +897,7 @@ def embed_merge_merge(ctx, change): @formatter.compact(event="merge/merge") -def compact_merge_merge(ctx, change): +def compact_merge_merge(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) parsed_comment = compact_summary(ctx) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) @@ -899,7 +913,7 @@ def compact_merge_merge(ctx, change): @formatter.embed(event="newusers/autocreate", mode="embed") -def embed_newusers_autocreate(ctx, change): +def embed_newusers_autocreate(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -908,7 +922,7 @@ def embed_newusers_autocreate(ctx, change): @formatter.compact(event="newusers/autocreate") -def compact_newusers_autocreate(ctx, change): +def compact_newusers_autocreate(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) content = ctx._("Account [{author}]({author_url}) was created automatically").format(author=author, author_url=author_url) @@ -919,7 +933,7 @@ def compact_newusers_autocreate(ctx, change): @formatter.embed(event="newusers/create", mode="embed") -def embed_newusers_create(ctx, change): +def embed_newusers_create(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -928,7 +942,7 @@ def embed_newusers_create(ctx, change): @formatter.compact(event="newusers/create") -def compact_newusers_create(ctx, change): +def compact_newusers_create(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) content = ctx._("Account [{author}]({author_url}) was created").format(author=author, author_url=author_url) return DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url, content=content) @@ -938,7 +952,7 @@ def compact_newusers_create(ctx, change): @formatter.embed(event="newusers/create2", mode="embed") -def embed_newusers_create2(ctx, change): +def embed_newusers_create2(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -947,7 +961,7 @@ def embed_newusers_create2(ctx, change): @formatter.compact(event="newusers/create2") -def compact_newusers_create2(ctx, change): +def compact_newusers_create2(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) parsed_comment = compact_summary(ctx) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) @@ -960,7 +974,7 @@ def compact_newusers_create2(ctx, change): @formatter.embed(event="newusers/byemail", mode="embed") -def embed_newusers_byemail(ctx, change): +def embed_newusers_byemail(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -970,7 +984,7 @@ def embed_newusers_byemail(ctx, change): @formatter.compact(event="newusers/byemail") -def compact_newusers_byemail(ctx, change): +def compact_newusers_byemail(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) parsed_comment = compact_summary(ctx) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) @@ -984,7 +998,7 @@ def compact_newusers_byemail(ctx, change): @formatter.embed(event="newusers/newusers", mode="embed") -def embed_newusers_newusers(ctx, change): +def embed_newusers_newusers(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed["url"] = ctx.client.create_article_path(sanitize_to_url("User:{}".format(change["user"]))) @@ -993,36 +1007,17 @@ def embed_newusers_newusers(ctx, change): @formatter.compact(event="newusers/newusers") -def compact_newusers_newusers(ctx, change): +def compact_newusers_newusers(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) content = ctx._("Account [{author}]({author_url}) was created").format(author=author, author_url=author_url) return DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url, content=content) -# newusers/reclaim - New user reclaimed - - -@formatter.embed(event="newusers/reclaim", mode="embed") -def embed_newusers_reclaim(ctx, change): - embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) - embed_helper(ctx, embed, change) - embed["url"] = ctx.client.create_article_path(sanitize_to_url("User:{}".format(change["user"]))) - embed["title"] = ctx._("Reclaimed account") - return embed - - -@formatter.compact(event="newusers/reclaim") -def compact_newusers_reclaim(ctx, change): - author, author_url = compact_author(ctx, change) - content = ctx._("Account [{author}]({author_url}) was reclaimed").format(author=author, author_url=author_url) - return DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url, content=content) - - # contentmodel/change - Changing the content model of a page @formatter.embed(event="contentmodel/change", mode="embed") -def embed_contentmodel_change(ctx, change): +def embed_contentmodel_change(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change, set_desc=False) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -1035,7 +1030,7 @@ def embed_contentmodel_change(ctx, change): @formatter.compact(event="contentmodel/change") -def compact_contentmodel_change(ctx, change): +def compact_contentmodel_change(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) parsed_comment = compact_summary(ctx) @@ -1051,7 +1046,7 @@ def compact_contentmodel_change(ctx, change): @formatter.embed(event="contentmodel/new", mode="embed") -def embed_contentmodel_new(ctx, change): +def embed_contentmodel_new(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change, set_desc=False) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -1063,7 +1058,7 @@ def embed_contentmodel_new(ctx, change): @formatter.compact(event="contentmodel/new") -def compact_contentmodel_new(ctx, change): +def compact_contentmodel_new(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) parsed_comment = compact_summary(ctx) @@ -1078,7 +1073,7 @@ def compact_contentmodel_new(ctx, change): @formatter.embed(event="managetags/create", mode="embed") -def embed_managetags_create(ctx, change): +def embed_managetags_create(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) ctx.client.refresh_internal_data() @@ -1088,7 +1083,7 @@ def embed_managetags_create(ctx, change): @formatter.compact(event="managetags/create") -def compact_managetags_create(ctx, change): +def compact_managetags_create(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) ctx.client.refresh_internal_data() @@ -1110,7 +1105,7 @@ def compact_managetags_create(ctx, change): @formatter.embed(event="managetags/delete", mode="embed") -def embed_managetags_delete(ctx, change): +def embed_managetags_delete(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) ctx.client.refresh_internal_data() embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -1123,7 +1118,7 @@ def embed_managetags_delete(ctx, change): @formatter.compact(event="managetags/delete") -def compact_managetags_delete(ctx, change): +def compact_managetags_delete(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) ctx.client.refresh_internal_data() @@ -1152,7 +1147,7 @@ def compact_managetags_delete(ctx, change): @formatter.embed(event="managetags/activate", mode="embed") -def embed_managetags_activate(ctx, change): +def embed_managetags_activate(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -1161,7 +1156,7 @@ def embed_managetags_activate(ctx, change): @formatter.compact(event="managetags/activate") -def compact_managetags_activate(ctx, change): +def compact_managetags_activate(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) parsed_comment = compact_summary(ctx) @@ -1180,7 +1175,7 @@ def compact_managetags_activate(ctx, change): @formatter.embed(event="managetags/deactivate", mode="embed") -def embed_managetags_deactivate(ctx, change): +def embed_managetags_deactivate(ctx: Context, change: dict): embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) embed_helper(ctx, embed, change) embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) @@ -1189,7 +1184,7 @@ def embed_managetags_deactivate(ctx, change): @formatter.compact(event="managetags/deactivate") -def compact_managetags_deactivate(ctx, change): +def compact_managetags_deactivate(ctx: Context, change: dict): author, author_url = compact_author(ctx, change) link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) parsed_comment = compact_summary(ctx) diff --git a/extensions/base/templateclassification.py b/extensions/base/templateclassification.py new file mode 100644 index 0000000..1b871ae --- /dev/null +++ b/extensions/base/templateclassification.py @@ -0,0 +1,47 @@ +# 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 . + + +import logging +from src.discord.message import DiscordMessage +from src.api import formatter +from src.api.context import Context +from src.api.util import embed_helper, compact_author, clean_link, sanitize_to_markdown, sanitize_to_url + + +# TemplateClassification - https://community.fandom.com/wiki/Help:Template_types +# templateclassification/tc-changed - Changing the type of a template + + +@formatter.embed(event="templateclassification/tc-changed") +def embed_templateclassification_changed(ctx: Context, change: dict) -> DiscordMessage: + embed = DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url) + embed_helper(ctx, embed, change, set_desc=False) + embed["url"] = ctx.client.create_article_path(sanitize_to_url(change["title"])) + embed["title"] = ctx._("Changed the type of {article}").format(article=sanitize_to_markdown(change["title"])) + embed["description"] = ctx._("Type changed from {old} to {new}").format( + old=change["logparams"]["oldtype"], new=change["logparams"]["newtype"]) + return embed + + +@formatter.compact(event="templateclassification/tc-changed") +def compact_templateclassification_changed(ctx: Context, change: dict): + author, author_url = compact_author(ctx, change) + link = clean_link(ctx.client.create_article_path(sanitize_to_url(change["title"]))) + content = ctx._( + "[{author}]({author_url}) changed the type of [{article}]({article_url}) from {old} to {new}").format( + author=author, author_url=author_url, article=sanitize_to_markdown(change["title"]), article_url=link, + old=change["logparams"]["oldtype"], new=change["logparams"]["newtype"]) + return DiscordMessage(ctx.message_type, ctx.event, ctx.webhook_url, content=content) diff --git a/src/api/util.py b/src/api/util.py index f95af0d..a861bbc 100644 --- a/src/api/util.py +++ b/src/api/util.py @@ -77,12 +77,12 @@ def compact_summary(ctx: Context) -> str: return "" -def compact_author(ctx: Context, change: dict) -> (Optional[str], Optional[str]): +def compact_author(ctx: Context, change: dict, is_anon: Optional[bool] = None) -> (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(ctx.client.create_article_path("User:{user}".format(user=sanitize_to_url(change["user"])))) - if "anon" in change: + if "anon" in change if is_anon is None else is_anon: if settings.get("hide_ips", False): author = ctx._("Unregistered user") else: @@ -92,7 +92,7 @@ def compact_author(ctx: Context, change: dict) -> (Optional[str], Optional[str]) return author, author_url -def embed_helper(ctx: Context, message: DiscordMessage, change: dict, set_user=True, set_edit_meta=True, set_desc=True) -> None: +def embed_helper(ctx: Context, message: DiscordMessage, change: dict, set_user=True, set_edit_meta=True, set_desc=True, is_anon: Optional[bool] = None) -> None: """Helps in preparing common edit/log fields for events. Passed arguments automatically become saturated with needed data. All automatic setups can be disabled by setting relevant variable to False @@ -103,7 +103,7 @@ def embed_helper(ctx: Context, message: DiscordMessage, change: dict, set_user=T setting default description (to ctx.parsedcomment)""" if set_user: author = None - if "anon" in change: + if "anon" in change if is_anon is None else is_anon: author_url = ctx.client.create_article_path("Special:Contributions/{user}".format(user=sanitize_to_url(change["user"]))) # logger.debug("current user: {} with cache of IPs: {}".format(change["user"], ip_mapper.keys())) if ctx.settings.get("hide_ips", False):