diff --git a/extensions/hooks/matrix.py b/extensions/hooks/matrix.py new file mode 100644 index 0000000..40612da --- /dev/null +++ b/extensions/hooks/matrix.py @@ -0,0 +1,118 @@ +# 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 time +from typing import Optional + +import requests +import markdown +import json + +from src.configloader import settings +from src.api.context import Context +from src.discord.message import DiscordMessage, DiscordMessageMetadata +from src.api.hook import post_hook + +# { +# "hooks": { +# "matrix": { +# "homeserver": "https://example.com/endpoint", +# "rooms": [], +# "access_token": "authtoken", +# "matrix_only": true +# } +# } +# } + +matrix_hook: Optional[dict] = None +start_time = int(time.time()) + + +def check_if_exists(settings: dict): + global matrix_hook + matrix_hook = settings.get("hooks", {}).get("matrix", {}) + return bool(matrix_hook) + + +@post_hook(priority=50, register=check_if_exists) +def matrix_posthook(message: DiscordMessage, metadata: DiscordMessageMetadata, context: Context, change: dict): + if not matrix_hook.get("access_token"): + raise KeyError("Matrix hook requires an access token to run!") + + if settings["appearance"]["mode"] == "embed": + matrix_json_formatted_body = discord_embed_converter(message).replace("\\:", ":").replace("\\|", "|") + else: + matrix_json_formatted_body = discord_compact_converter(message) + if matrix_hook.get("matrix_only"): + context.event = None + + data = json.dumps({"msgtype": "m.text", "body": "test", "format": "org.matrix.custom.html", "formatted_body": matrix_json_formatted_body}) + for room in matrix_hook.get("rooms", []): + response = requests.put("{homeserver}/_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}".format(homeserver=matrix_hook.get("homeserver"), + roomId=room, + eventType="m.room.message", + txnId=str(int(change["rcid"])+start_time)), + data=data, headers={"Authorization": "Bearer "+matrix_hook.get("access_token"), "Content-Type": "application/json"}) + print(response.status_code) + print(response.text) + + +def discord_embed_converter(embed: DiscordMessage) -> str: + discord_embed = embed.embed + matrix_soup = [] + + matrix_soup.append("{author}
".format(author=discord_embed.get("author", {}).get("name", "unknown"), url=discord_embed.get("author", {}).get("url", ""))) + matrix_soup.append("{title}
".format(title=discord_embed.get("title", "Unknown title"), url=discord_embed.get("url", ""))) + if discord_embed.get("description"): + matrix_soup.append(markdown.markdown(discord_embed.get("description", ""), extensions=['pymdownx.tilde'])) + for field in discord_embed.get("fields", []): + if field.get("inline"): + matrix_soup.append((markdown.markdown(field.get("value", ""), extensions=['pymdownx.tilde']), True)) + else: + matrix_soup.append(("{name}
{data}".format(name=field.get("name", ""), data=removep(markdown.markdown(field.get("value", ""), extensions=['pymdownx.tilde']))), False)) + final_output = "" + in_table_mode = False + while matrix_soup: + element = matrix_soup.pop(0) + if isinstance(element, str): + element = removep(element) + if in_table_mode: + final_output += "" + in_table_mode = False + final_output += element + else: + if in_table_mode is False: + final_output+="" + in_table_mode = True + if element[1] is False: + final_output+="" + else: + if matrix_soup and matrix_soup[0][1] is True: + another_element = matrix_soup.pop(0) + final_output+="" + else: + final_output += "" + if in_table_mode: + final_output += "
"+removep(element[0])+"
"+removep(element[0])+""+removep(another_element[0])+"
" + removep(element[0]) + "
" + return final_output.replace("\n", "") + + +def removep(element: str) -> str: + if element.startswith("

") and element.endswith("

"): + return element[3:-4] + return element + + +def discord_compact_converter(embed: DiscordMessage) -> str: + return markdown.markdown(embed.webhook_object["content"], extensions=['pymdownx.tilde']) \ No newline at end of file diff --git a/src/misc.py b/src/misc.py index 83f8504..bf49f50 100644 --- a/src/misc.py +++ b/src/misc.py @@ -21,7 +21,7 @@ from typing import Callable, Tuple, List, Optional, Union from urllib.parse import urlparse, urlunparse import requests -from api.context import Context +from src.api.context import Context from src.argparser import command_args from src.configloader import settings import src.api.util diff --git a/src/rcgcdw.py b/src/rcgcdw.py index c9588d8..2ae2ba7 100644 --- a/src/rcgcdw.py +++ b/src/rcgcdw.py @@ -286,6 +286,8 @@ def rc_processor(change, changed_categories): for revid in logparams.get("ids", []): delete_messages(dict(revid=revid)) run_hooks(post_hooks, discord_message, metadata, context, change) + if not context.event: + return if discord_message: discord_message.finish_embed() send_to_discord(discord_message, metadata) @@ -311,6 +313,8 @@ def abuselog_processing(entry): raise metadata = DiscordMessageMetadata("POST") run_hooks(post_hooks, discord_message, metadata, context, entry) + if not context.event: + return discord_message.finish_embed() send_to_discord(discord_message, metadata)