Merge branch 'matrix/start-creating-tag-rooms' into 'master'

Start creating tag rooms and carbon copying posts to them based on the tags they contain

See merge request jaywink/federation!166
jsonld-processing
jaywink 2021-05-08 21:37:11 +00:00
commit 0291d9dd98
2 zmienionych plików z 84 dodań i 1 usunięć

Wyświetl plik

@ -2,16 +2,19 @@ import json
import logging
import mimetypes
import os
from typing import Dict, List
from typing import Dict, List, Optional
from urllib.parse import quote
from uuid import uuid4
import requests
# noinspection PyPackageRequirements
from slugify import slugify
from federation.entities.base import Post, Profile
from federation.entities.matrix.enums import EventType
from federation.entities.mixins import BaseEntity
from federation.entities.utils import get_base_attributes, get_profile
from federation.utils.django import get_configuration
from federation.utils.matrix import get_matrix_configuration, appservice_auth_header
from federation.utils.network import fetch_document, fetch_file
@ -88,6 +91,55 @@ class MatrixRoomMessage(Post, MatrixEntityMixin):
_thread_room_event_id: str = None
_thread_room_id: str = None
def add_tag_room_payloads(self, tag_room_id: str):
self._payloads.append({
"endpoint": f"{super().get_endpoint()}/rooms/{tag_room_id}/join?user_id={self.mxid}",
"payload": {},
})
self._payloads.append({
# TODO at some point we'll need to track the event_id's, for now just random
# When we start listening to events from the other side, we'll need to filter
# the ones we sent. Additionally if there is going to be some kind of symlink MSC,
# we're going to want to stop carbon copying to many rooms.
"endpoint": f"{super().get_endpoint()}/rooms/{tag_room_id}/send/{self.event_type}/"
f"{str(uuid4())}?user_id={self.mxid}",
"payload": {
"body": self.raw_content,
"msgtype": "m.text",
"format": "org.matrix.custom.html",
"formatted_body": self.rendered_content,
},
"method": "put",
})
def create_tag_room(self, tag: str) -> str:
headers = appservice_auth_header()
config = get_configuration()
topic = f"Content for the tag #{tag}."
if config.get("tags_path"):
topic += f" Mirrored from {config['base_url']}{config['tags_path'].replace(':tag:', slugify(tag))}"
matrix_config = get_matrix_configuration()
response = requests.post(
url=f"{super().get_endpoint()}/createRoom",
json={
"preset": "public_chat",
"name": f"#{tag} ({matrix_config['appservice']['shortcode']} | {matrix_config['homeserver_name']})",
"room_alias_name": self.get_tag_room_alias_localpart(tag).strip('#'),
"topic": topic,
},
headers=headers,
)
response.raise_for_status()
room_id = response.json()["room_id"]
self._payloads.append({
"endpoint": f"{super().get_endpoint()}/directory/list/room/{room_id}",
"payload": {
"visibility": "public",
},
"method": "put",
})
return room_id
def create_thread_room(self):
headers = appservice_auth_header()
# Create the thread room
@ -129,6 +181,24 @@ class MatrixRoomMessage(Post, MatrixEntityMixin):
if payloads:
self._payloads.extend(payloads)
@staticmethod
def get_tag_room_alias_localpart(tag: str) -> str:
config = get_matrix_configuration()
return f"#_{config['appservice']['shortcode']}_#{slugify(tag)}"
def get_tag_room_alias_url_safe(self, tag: str) -> str:
return quote(f"{self.get_tag_room_alias_localpart(tag)}:{self.server_name}")
def get_tag_room_id(self, tag: str) -> Optional[str]:
# TODO: we should cache these.
doc, status, error = fetch_document(
url=f"{self.get_endpoint()}/directory/room/{self.get_tag_room_alias_url_safe(tag)}",
extra_headers=appservice_auth_header(),
)
if status == 200:
data = json.loads(doc)
return data["room_id"]
def payloads(self) -> List[Dict]:
payloads = super().payloads()
payloads.append({
@ -168,6 +238,18 @@ class MatrixRoomMessage(Post, MatrixEntityMixin):
self.upload_embedded_images()
# Create thread room
self.create_thread_room()
# Process tags if public post
if self.public:
for tag in self.tags:
tag_room_id = self.get_tag_room_id(tag)
if not tag_room_id:
# noinspection PyBroadException
try:
tag_room_id = self.create_tag_room(tag)
except Exception as ex:
logger.warning("Failed to create tag room for tag %s for post %s: %s", tag, self.id, ex)
continue
self.add_tag_room_payloads(tag_room_id)
def upload_embedded_images(self):
"""

Wyświetl plik

@ -38,6 +38,7 @@ setup(
"jsonschema>=2.0.0",
"pycryptodome>=3.4.10",
"python-dateutil>=2.4.0",
"python-slugify>=5.0.0",
"python-xrd>=0.1",
"pytz",
"PyYAML",