Prepare for room v3+, misc bugfixes

This commit is contained in:
2025-10-24 23:42:29 -04:00
parent b71096663c
commit f23a74de5c
8 changed files with 288 additions and 254 deletions

View File

@@ -44,7 +44,7 @@ async def validate_json():
try:
request.get_json(force=True)
except Exception as e:
except Exception:
return jsonify({"error": "Content not JSON.", "errcode": "M_NOT_JSON"}), 400

View File

@@ -621,7 +621,7 @@ async def url_preview():
@client.route("/_matrix/client/v1/media/preview_url")
async def media_preview():
response = send_file(config.cat)
response.headers["Content-Disposition"] = f'inline; filename="cat.jpg"'
response.headers["Content-Disposition"] = 'inline; filename="cat.jpg"'
response.headers["Content-Type"] = "image/jpg"
return response

View File

@@ -1,4 +1,3 @@
from vona.config import the_funny_number
from datetime import datetime, timezone
from vona.federation import send_join
import vona.globals as globals
@@ -7,7 +6,6 @@ import time
from flask import (
Blueprint,
request,
jsonify,
)

View File

@@ -2,15 +2,12 @@ from vona.federation import send_join
import vona.globals as globals
import vona.config as config
import base64
import re
import os
from flask import (
Blueprint,
jsonify,
request,
Response,
)
synapse = Blueprint("synapse", __name__)
@@ -99,7 +96,7 @@ async def whois(user_id):
"": {
"sessions": [{
"connections": [{
"ip":f"127.0.0.1",
"ip":"127.0.0.1",
"last_seen":config.the_funny_number,
"user_agent":f"Vona/{globals.version}"
}]

View File

@@ -1,16 +1,14 @@
import vona.federation.rooms as rooms
import vona.globals as globals
import vona.config as config
import threading
import json
import time
import os
from flask import (
jsonify,
Response,
request,
send_file,
Blueprint,
)
@@ -23,210 +21,8 @@ class bullshit:
return {}
def send_join(request, room) -> dict:
event_chain = []
event_hashes = []
event_ids = [
globals.make_event_id(seed=f"1_{room}"),
globals.make_event_id(seed=f"2_{room}"),
globals.make_event_id(seed=f"3_{room}"),
globals.make_event_id(seed=f"4_{room}"),
globals.make_event_id(seed=f"5_{room}"),
globals.make_event_id(seed=f"6_{room}"),
]
create_event = {
"content": {
"m.federate": True,
"creator": f"@vona:{config.server_name}",
"room_version": globals.room_version_from_id(room)
},
"event_id": event_ids[0],
"origin_server_ts": 1,
"room_id": room,
"sender": f"@vona:{config.server_name}",
"state_key": "",
"depth": 1,
"type": "m.room.create",
"auth_events": [],
"prev_events": []
}
screate_event = globals.hash_and_sign_event(create_event)
event_chain.append(screate_event)
our_join = {
"content": {
"displayname": "Vona",
"avatar_url": f"mxc://{config.server_name}/cat",
"membership": "join"
},
"origin_server_ts": 2,
"sender": f"@vona:{config.server_name}",
"state_key": f"@vona:{config.server_name}",
"type": "m.room.member",
"event_id": event_ids[1],
"room_id": room,
"depth": 2,
"auth_events": [[
screate_event["event_id"],
screate_event["hashes"]
]],
"prev_events": [[
screate_event["event_id"],
screate_event["hashes"]
]]
}
sour_join = globals.hash_and_sign_event(our_join)
event_chain.append(sour_join)
pls = {
"content": {
"users": {
f"@vona:{config.server_name}": "100"
}
},
"origin_server_ts": 3,
"room_id": room,
"sender": f"@vona:{config.server_name}",
"state_key": "",
"type": "m.room.power_levels",
"event_id": event_ids[2],
"depth": 3,
"user_id": f"@vona:{config.server_name}",
"auth_events": [
[
screate_event["event_id"],
screate_event["hashes"]
],
[
sour_join["event_id"],
sour_join["hashes"]
]
],
"prev_events": [[
sour_join["event_id"],
sour_join["hashes"]
]]
}
spls = globals.hash_and_sign_event(pls)
event_chain.append(spls)
join_rule = {
"content": {
"join_rule": "public"
},
"origin_server_ts": 4,
"sender": f"@vona:{config.server_name}",
"state_key": "",
"type": "m.room.join_rules",
"event_id": event_ids[3],
"room_id": room,
"depth": 4,
"auth_events": [
[
screate_event["event_id"],
screate_event["hashes"]
],
[
sour_join["event_id"],
sour_join["hashes"]
],
[
spls["event_id"],
spls["hashes"]
]
],
"prev_events": [[
spls["event_id"],
spls["hashes"]
]]
}
sjoin_rule = globals.hash_and_sign_event(join_rule)
event_chain.append(sjoin_rule)
guest_access = {
"content": {
"guest_access": "forbidden"
},
"origin_server_ts": 5,
"depth": 5,
"sender": f"@vona:{config.server_name}",
"state_key": "",
"type": "m.room.guest_access",
"event_id": event_ids[4],
"room_id": room,
"auth_events": [
[
screate_event["event_id"],
screate_event["hashes"]
],
[
sour_join["event_id"],
sour_join["hashes"]
],
[
spls["event_id"],
spls["hashes"]
]
],
"prev_events": [[
sjoin_rule["event_id"],
sjoin_rule["hashes"]
]]
}
sguest_access = globals.hash_and_sign_event(guest_access)
event_chain.append(sguest_access)
history = {
"content": {
"history_visibility": "shared"
},
"type": "m.room.history_visibility",
"sender": f"@vona:{config.server_name}",
"state_key": "",
"origin_server_ts": 6,
"depth": 6,
"event_id": event_ids[5],
"room_id": room,
"auth_events": [
[
screate_event["event_id"],
screate_event["hashes"]
],
[
sour_join["event_id"],
sour_join["hashes"]
],
[
spls["event_id"],
spls["hashes"]
]
],
"prev_events": [[
sguest_access["event_id"],
sguest_access["hashes"]
]]
}
shistory = globals.hash_and_sign_event(history)
event_chain.append(shistory)
remote_join = request.get_json()
response = {
"auth_chain": event_chain,
"event": remote_join,
"members_omitted": False,
"servers_in_room": [config.server_name],
"state": event_chain
}
return response
if globals.room_version_from_id(room) in ["1", "2"]:
return rooms.v1_v2(request, room)
@server.route("/_matrix/federation/v1/version")
@@ -288,27 +84,39 @@ async def thumbnail_media(media_id):
"error": "Cat is too cute to thumbnail"
}), 418
@server.route("/_matrix/federation/v1/send_join/<room>/<eventId>", methods=["PUT"])
async def send_join_v1(room, eventId):
if globals.room_version_from_id(room) not in ["1", "2"]:
return jsonify({
"errcode": "M_INCOMPATIBLE_ROOM_VERSION",
"error": "This room is not v1 or v2."
}), 400
return jsonify([200, send_join(request, room)])
@server.route("/_matrix/federation/v2/send_join/<room>/<eventId>", methods=["PUT"])
async def send_join_v2(room, eventId):
return jsonify(send_join(request, room))
@server.route("/_matrix/federation/v1/make_join/<room>/<user>")
async def make_join(room, user):
def not_invited():
if ":" in room:
if room.split(":")[1] != config.server_name:
return jsonify({
"errcode": "M_FORBIDDEN",
"error": "You are not invited to this room."
}), 403
else:
return jsonify({
"errcode": "M_FORBIDDEN",
"error": "You are not invited to this room."
}), 403
try:
if room.split(":")[1] != config.server_name:
return not_invited()
except:
return not_invited()
room_ver = globals.room_version_from_id(room)
state = send_join(
request=bullshit,
@@ -329,29 +137,43 @@ async def make_join(room, user):
"depth": 7
}
join["auth_events"] = [
[
state[0]["event_id"],
state[0]["hashes"]
],
[
state[2]["event_id"],
state[2]["hashes"]
],
[
state[3]["event_id"],
state[3]["hashes"]
]
]
if room_ver in ["1", "2"]:
join["event_id"] = globals.make_event_id(seed=f"{user}+{room}")
join["auth_events"] = [
[
state[0]["event_id"],
state[0]["hashes"]
],
[
state[2]["event_id"],
state[2]["hashes"]
],
[
state[3]["event_id"],
state[3]["hashes"]
]
]
join["prev_events"] = [[
state[5]["event_id"],
state[5]["hashes"]
]]
else:
join["auth_events"] = [
globals.make_ref_hash(state[0], int(room_ver)),
globals.make_ref_hash(state[2], int(room_ver)),
globals.make_ref_hash(state[3], int(room_ver)),
]
join["prev_events"] = [
globals.make_ref_hash(state[5], int(room_ver)),
]
join["prev_events"] = [[
state[5]["event_id"],
state[5]["hashes"]
]]
return jsonify({
"event": globals.hash_and_sign_event(join),
"room_version": globals.room_version_from_id(room)
"room_version": room_ver
})
@@ -475,8 +297,7 @@ async def invite_user_v1(room, txnId):
and ":" in event["event_id"]
):
return jsonify({
"event": globals.sign_json_without_discard(event),
"room_version": invite_data["room_version"]
"event": globals.sign_json_without_discard(event)
})
return jsonify({
@@ -550,7 +371,12 @@ async def state_ids(room):
event_ids = []
for event in state:
event_ids.append(event["event_id"])
if "event_id" in event:
event_ids.append(event["event_id"])
else:
event_ids.append(
globals.make_ref_hash(event)
)
if evt in event_ids:
return jsonify({

213
vona/federation/rooms.py Normal file
View File

@@ -0,0 +1,213 @@
import vona.globals as globals
import vona.config as config
# This file is responsible for creating Matrix rooms.
# Room V3+
# TODO
# Room V1/V2
def v1_v2(request, room) -> dict:
event_chain = []
event_ids = [
globals.make_event_id(seed=f"1_{room}"),
globals.make_event_id(seed=f"2_{room}"),
globals.make_event_id(seed=f"3_{room}"),
globals.make_event_id(seed=f"4_{room}"),
globals.make_event_id(seed=f"5_{room}"),
globals.make_event_id(seed=f"6_{room}"),
]
create_event = {
"content": {
"m.federate": True,
"creator": f"@vona:{config.server_name}",
"room_version": globals.room_version_from_id(room)
},
"event_id": event_ids[0],
"origin_server_ts": 1,
"room_id": room,
"sender": f"@vona:{config.server_name}",
"state_key": "",
"depth": 1,
"type": "m.room.create",
"auth_events": [],
"prev_events": []
}
screate_event = globals.hash_and_sign_event(create_event)
event_chain.append(screate_event)
our_join = {
"content": {
"displayname": "Vona",
"avatar_url": f"mxc://{config.server_name}/cat",
"membership": "join"
},
"origin_server_ts": 2,
"sender": f"@vona:{config.server_name}",
"state_key": f"@vona:{config.server_name}",
"type": "m.room.member",
"event_id": event_ids[1],
"room_id": room,
"depth": 2,
"auth_events": [[
screate_event["event_id"],
screate_event["hashes"]
]],
"prev_events": [[
screate_event["event_id"],
screate_event["hashes"]
]]
}
sour_join = globals.hash_and_sign_event(our_join)
event_chain.append(sour_join)
pls = {
"content": {
"users": {
f"@vona:{config.server_name}": "100"
}
},
"origin_server_ts": 3,
"room_id": room,
"sender": f"@vona:{config.server_name}",
"state_key": "",
"type": "m.room.power_levels",
"event_id": event_ids[2],
"depth": 3,
"user_id": f"@vona:{config.server_name}",
"auth_events": [
[
screate_event["event_id"],
screate_event["hashes"]
],
[
sour_join["event_id"],
sour_join["hashes"]
]
],
"prev_events": [[
sour_join["event_id"],
sour_join["hashes"]
]]
}
spls = globals.hash_and_sign_event(pls)
event_chain.append(spls)
join_rule = {
"content": {
"join_rule": "public"
},
"origin_server_ts": 4,
"sender": f"@vona:{config.server_name}",
"state_key": "",
"type": "m.room.join_rules",
"event_id": event_ids[3],
"room_id": room,
"depth": 4,
"auth_events": [
[
screate_event["event_id"],
screate_event["hashes"]
],
[
sour_join["event_id"],
sour_join["hashes"]
],
[
spls["event_id"],
spls["hashes"]
]
],
"prev_events": [[
spls["event_id"],
spls["hashes"]
]]
}
sjoin_rule = globals.hash_and_sign_event(join_rule)
event_chain.append(sjoin_rule)
guest_access = {
"content": {
"guest_access": "forbidden"
},
"origin_server_ts": 5,
"depth": 5,
"sender": f"@vona:{config.server_name}",
"state_key": "",
"type": "m.room.guest_access",
"event_id": event_ids[4],
"room_id": room,
"auth_events": [
[
screate_event["event_id"],
screate_event["hashes"]
],
[
sour_join["event_id"],
sour_join["hashes"]
],
[
spls["event_id"],
spls["hashes"]
]
],
"prev_events": [[
sjoin_rule["event_id"],
sjoin_rule["hashes"]
]]
}
sguest_access = globals.hash_and_sign_event(guest_access)
event_chain.append(sguest_access)
history = {
"content": {
"history_visibility": "shared"
},
"type": "m.room.history_visibility",
"sender": f"@vona:{config.server_name}",
"state_key": "",
"origin_server_ts": 6,
"depth": 6,
"event_id": event_ids[5],
"room_id": room,
"auth_events": [
[
screate_event["event_id"],
screate_event["hashes"]
],
[
sour_join["event_id"],
sour_join["hashes"]
],
[
spls["event_id"],
spls["hashes"]
]
],
"prev_events": [[
sguest_access["event_id"],
sguest_access["hashes"]
]]
}
shistory = globals.hash_and_sign_event(history)
event_chain.append(shistory)
remote_join = request.get_json()
response = {
"auth_chain": event_chain,
"event": remote_join,
"members_omitted": False,
"servers_in_room": [config.server_name],
"state": event_chain
}
return response

View File

@@ -7,7 +7,6 @@ import hashlib
import base64
import random
import httpx
import copy
import json
import re
@@ -263,14 +262,15 @@ def make_ref_hash(
def room_version_from_id(room):
room_id_no_sigil = room.replace("!", "")
hexadecimal_room_id = bytes(room_id_no_sigil, "utf-8").hex()
if "1" not in hexadecimal_room_id and "2" not in hexadecimal_room_id:
hexadecimal_room_id = "1" + hexadecimal_room_id[1:]
versions = [str(i) for i in range(1, 3)]
if not any(ver in hexadecimal_room_id for ver in versions):
hexadecimal_room_id = "2" + hexadecimal_room_id[1:]
def remove_chars(s):
return re.sub("[^12]", "", s)
return re.sub(f"[^{''.join(versions)}]", "", s)
nums = remove_chars(hexadecimal_room_id)
@@ -278,9 +278,9 @@ def room_version_from_id(room):
s = s.replace(" ", "").lower()
counts = Counter(s)
most_common = counts.most_common(1)
return most_common[0] if most_common else None
return most_common[0] if most_common else ("2",)
return most_common_character(nums)[0]
return str(most_common_character(nums)[0])
room_dir = {

View File

@@ -133,11 +133,11 @@ async def invite():
"public_keys": [
{
"key_validity_url": f"https://{server_name}/_matrix/identity/v2/pubkey/isvalid",
"public_key":"ohyeah"
"public_key": "ohyeah"
},
{
"key_validity_url": f"https://{server_name}/_matrix/identity/v2/pubkey/ephemeral/isvalid",
"public_key":"thisssssss"
"public_key": "burgerkingfootlettuce"
}
],
"token": "vona"
@@ -148,10 +148,10 @@ async def invite():
@identity.route("/_matrix/identity/v2/sign-ed25519", methods=["POST"])
async def invite_signing():
required_keys = {"mxid", "private_key", "token"}
d = data.get_json()
d = request.data.get_json()
if set(d.keys()) == required_keys:
return jsonify(sign_json(d))
return jsonify(globals.sign_json(d))
else:
return jsonify({
"errcode": "M_UNRECOGNIZED",