Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
492ffc62e9
|
|||
|
9ca4c913f3
|
|||
|
6dd4fb04e3
|
|||
|
f771130a16
|
|||
|
9aa2e062e5
|
|||
|
c8d6f57e5b
|
|||
|
753625ad5c
|
|||
|
74a36e0b34
|
|||
|
b178011ad9
|
|||
|
76f89beb29
|
|||
|
7e8eb6de7f
|
|||
|
4e28507dea
|
|||
|
357d3b7429
|
3
SECURITY.md
Normal file
3
SECURITY.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Security
|
||||||
|
If you believe you have found a vulnerability in Vona, please email vel@riseup.net or DM `@vel:faelix.im` on Matrix.
|
||||||
|
Do not disclose the details of the vulnerability until a public fix has been made.
|
||||||
@@ -8,6 +8,7 @@ dependencies = [
|
|||||||
"httpx (>=0.28.1,<0.29.0)",
|
"httpx (>=0.28.1,<0.29.0)",
|
||||||
"pynacl (>=1.6.0,<2.0.0)",
|
"pynacl (>=1.6.0,<2.0.0)",
|
||||||
"flask[async] (>=3.1.2,<4.0.0)",
|
"flask[async] (>=3.1.2,<4.0.0)",
|
||||||
|
"resolvematrix @ git+https://codeberg.org/timedout/resolvematrix.git",
|
||||||
]
|
]
|
||||||
|
|
||||||
authors = [
|
authors = [
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ async def handle_logging(response):
|
|||||||
response.headers["Access-Control-Allow-Methods"] = "GET, HEAD, POST, PUT, DELETE, OPTIONS"
|
response.headers["Access-Control-Allow-Methods"] = "GET, HEAD, POST, PUT, DELETE, OPTIONS"
|
||||||
|
|
||||||
if request.method == "OPTIONS":
|
if request.method == "OPTIONS":
|
||||||
# Discard logs for OPTIONS
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
origin = "unknown"
|
origin = "unknown"
|
||||||
@@ -57,13 +56,31 @@ async def handle_logging(response):
|
|||||||
try:
|
try:
|
||||||
if "Authorization" in request.headers:
|
if "Authorization" in request.headers:
|
||||||
if request.headers["Authorization"].split()[0] == "X-Matrix":
|
if request.headers["Authorization"].split()[0] == "X-Matrix":
|
||||||
origin = request.headers["Authorization"].split('origin="')[1].split('"')[0]
|
origin = (
|
||||||
|
request.headers["Authorization"]
|
||||||
|
.split("origin=")[1]
|
||||||
|
.split(",")[0]
|
||||||
|
)
|
||||||
|
|
||||||
|
while '"' in origin:
|
||||||
|
origin = origin.replace('"', "")
|
||||||
|
|
||||||
|
if origin == config.server_name:
|
||||||
|
return response
|
||||||
|
|
||||||
else:
|
else:
|
||||||
origin = "client"
|
origin = "client"
|
||||||
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
print(f'[{origin}] [{request.remote_addr}] [{datetime.now().strftime("%d/%b/%Y:%H:%M:%S")}] {request.method} {request.full_path} {response.status_code}')
|
print(
|
||||||
|
f"[{origin}] " +
|
||||||
|
f'[{datetime.now().strftime("%d/%b/%Y:%H:%M:%S")}] ' +
|
||||||
|
request.method + " " +
|
||||||
|
request.full_path.rstrip("?") + " " +
|
||||||
|
str(response.status_code)
|
||||||
|
)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@@ -115,7 +132,11 @@ async def client():
|
|||||||
|
|
||||||
def federation_self_test():
|
def federation_self_test():
|
||||||
try:
|
try:
|
||||||
resp = globals.http_client.get(f"https://{config.server_name}/.well-known/matrix/server")
|
resp = globals.http_client().get(
|
||||||
|
path="/",
|
||||||
|
destination=config.server_name,
|
||||||
|
)
|
||||||
|
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
print("[INFO] Federation self-test OK")
|
print("[INFO] Federation self-test OK")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ async def spec_versions():
|
|||||||
@client.route("/_matrix/client/v3/admin/whois/<user>")
|
@client.route("/_matrix/client/v3/admin/whois/<user>")
|
||||||
@client.route("/_matrix/client/r0/admin/whois/<user>")
|
@client.route("/_matrix/client/r0/admin/whois/<user>")
|
||||||
async def whois(user):
|
async def whois(user):
|
||||||
if userId.startswith("@"):
|
if user.startswith("@"):
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"devices": {
|
"devices": {
|
||||||
"": {
|
"": {
|
||||||
@@ -643,15 +643,11 @@ async def mutual_rooms():
|
|||||||
async def presence(user):
|
async def presence(user):
|
||||||
if request.method == "PUT":
|
if request.method == "PUT":
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({"presence": "online"})
|
||||||
"presence": "online"
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
@client.route("/_matrix/client/v3/publicRooms", methods=["GET", "POST"])
|
||||||
@client.route("/_matrix/client/r0/publicRooms", methods=["GET", "POST"])
|
@client.route("/_matrix/client/r0/publicRooms", methods=["GET", "POST"])
|
||||||
async def room_directory():
|
async def room_directory():
|
||||||
return jsonify({
|
return jsonify(globals.room_dir)
|
||||||
"chunk": [],
|
|
||||||
"total_room_count_estimate": 0
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -2,18 +2,21 @@ from flask import Blueprint
|
|||||||
|
|
||||||
custom = Blueprint("custom", __name__)
|
custom = Blueprint("custom", __name__)
|
||||||
|
|
||||||
# This implements custom endpoints
|
# This implements non-standard
|
||||||
# used by other homeserver
|
# endpoints created by other
|
||||||
# implementations. They do not start
|
# homeserver implementations.
|
||||||
# with /_matrix/
|
|
||||||
|
|
||||||
|
|
||||||
|
from .hammerhead import hammerhead
|
||||||
from .conduwuit import conduwuit
|
from .conduwuit import conduwuit
|
||||||
from .dendrite import dendrite
|
from .dendrite import dendrite
|
||||||
from .telodendria import telo
|
from .telodendria import telo
|
||||||
from .synapse import synapse
|
from .synapse import synapse
|
||||||
|
from .citadel import citadel
|
||||||
|
|
||||||
|
custom.register_blueprint(hammerhead)
|
||||||
custom.register_blueprint(conduwuit)
|
custom.register_blueprint(conduwuit)
|
||||||
custom.register_blueprint(dendrite)
|
custom.register_blueprint(dendrite)
|
||||||
custom.register_blueprint(synapse)
|
custom.register_blueprint(synapse)
|
||||||
|
custom.register_blueprint(citadel)
|
||||||
custom.register_blueprint(telo)
|
custom.register_blueprint(telo)
|
||||||
|
|||||||
61
vona/custom/citadel.py
Normal file
61
vona/custom/citadel.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
from flask import Blueprint, jsonify, request
|
||||||
|
import vona.config as config
|
||||||
|
import base64
|
||||||
|
import os
|
||||||
|
|
||||||
|
citadel = Blueprint("citadel", __name__)
|
||||||
|
|
||||||
|
# These are endpoints made by Thales Citadel
|
||||||
|
|
||||||
|
# TODO: Add more endpoints, this likely
|
||||||
|
# isn't all of them
|
||||||
|
|
||||||
|
|
||||||
|
@citadel.route("/_matrix/client/r0/citadel/stats/m.news/<event>", methods=["GET", "PUT"])
|
||||||
|
async def news_stats(event):
|
||||||
|
if request.method == "PUT":
|
||||||
|
return jsonify({"success": True})
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"total_clicks": config.the_funny_number,
|
||||||
|
"user_readings": config.the_funny_number
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@citadel.route("/_matrix/client/r0/citadel/rooms/<room>/closeRoom", methods=["POST"])
|
||||||
|
async def close_room(room):
|
||||||
|
store_response = request.json.get("store_response", True)
|
||||||
|
|
||||||
|
operation_id = base64.b64encode(
|
||||||
|
bytes(
|
||||||
|
os.urandom(8).hex(),
|
||||||
|
"utf-8"
|
||||||
|
)
|
||||||
|
).decode("utf-8")[:14]
|
||||||
|
|
||||||
|
|
||||||
|
if store_response:
|
||||||
|
resp = {"operation_id": operation_id}
|
||||||
|
else:
|
||||||
|
resp = {
|
||||||
|
"operation_id": operation_id,
|
||||||
|
"previous_state": {
|
||||||
|
"progress": {
|
||||||
|
"steps": {
|
||||||
|
"step_kick_users": {
|
||||||
|
"status": "complete"
|
||||||
|
},
|
||||||
|
"step_purge_history": {
|
||||||
|
"status": "complete"
|
||||||
|
},
|
||||||
|
"step_purge_media": {
|
||||||
|
"status": "complete"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": "complete"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return jsonify(resp)
|
||||||
77
vona/custom/hammerhead.py
Normal file
77
vona/custom/hammerhead.py
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
from flask import Blueprint, request, jsonify
|
||||||
|
from vona.config import the_funny_number
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
from vona.federation import send_join
|
||||||
|
import vona.globals as globals
|
||||||
|
import vona.config as config
|
||||||
|
import time
|
||||||
|
|
||||||
|
hammerhead = Blueprint("hammerhead", __name__)
|
||||||
|
|
||||||
|
# Hammerhead endpoints. Not documented, but code is at:
|
||||||
|
# https://codeberg.org/timedout/hammerhead/src/branch/dev/hammerhead/router/routes/hammerhead
|
||||||
|
|
||||||
|
|
||||||
|
@hammerhead.route("/_hammerhead/uptime")
|
||||||
|
async def uptime():
|
||||||
|
return jsonify({"started_at": config.the_funny_number})
|
||||||
|
|
||||||
|
@hammerhead.route("/_hammerhead/version")
|
||||||
|
async def version():
|
||||||
|
return jsonify({"version": globals.version})
|
||||||
|
|
||||||
|
|
||||||
|
@hammerhead.route("/_hammerhead/admin/server-info/<server>")
|
||||||
|
async def server_info(server):
|
||||||
|
return jsonify({
|
||||||
|
"destination": {
|
||||||
|
"expires": datetime.now(timezone.utc).isoformat(),
|
||||||
|
"host_header": server,
|
||||||
|
"ip_port": [
|
||||||
|
f"{server}:443"
|
||||||
|
],
|
||||||
|
"server_name": server
|
||||||
|
},
|
||||||
|
"keys": globals.sign_json({
|
||||||
|
"old_verify_keys": {},
|
||||||
|
"server_name": server,
|
||||||
|
"valid_until_ts": int(time.time() * 1000 + 604800000),
|
||||||
|
"verify_keys": {
|
||||||
|
f"ed25519:{config.signing_key.split()[1]}": {
|
||||||
|
"key": globals.pubkey()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
"software": {
|
||||||
|
"server": {
|
||||||
|
"version": globals.version,
|
||||||
|
"name": "Vona"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@hammerhead.route("/_hammerhead/admin/rooms/<room>/state-resolver")
|
||||||
|
async def room_state(room):
|
||||||
|
class bullshit:
|
||||||
|
def get_json():
|
||||||
|
return {}
|
||||||
|
|
||||||
|
state = send_join(bullshit, room)["state"]
|
||||||
|
formatted_state = {}
|
||||||
|
event_cache = {}
|
||||||
|
|
||||||
|
for event in state:
|
||||||
|
key = f"({event["type"]},'{event["state_key"]}')"
|
||||||
|
formatted_state[key] = event
|
||||||
|
|
||||||
|
event_id = event["event_id"]
|
||||||
|
event_cache[event_id] = event
|
||||||
|
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"current_state": formatted_state,
|
||||||
|
"event_cache": event_cache,
|
||||||
|
"room_id": room,
|
||||||
|
"room_version": globals.room_version_from_id(room)
|
||||||
|
})
|
||||||
@@ -24,9 +24,9 @@ synapse = Blueprint("synapse", __name__)
|
|||||||
@synapse.route("/_synapse/admin/v1/media/unquarantine/<s>/<media_id>", methods=["POST"])
|
@synapse.route("/_synapse/admin/v1/media/unquarantine/<s>/<media_id>", methods=["POST"])
|
||||||
@synapse.route("/_synapse/admin/v1/federation/destinations/<destination>/reset_connection", methods=["POST"])
|
@synapse.route("/_synapse/admin/v1/federation/destinations/<destination>/reset_connection", methods=["POST"])
|
||||||
@synapse.route("/_synapse/admin/v1/rooms/<room>")
|
@synapse.route("/_synapse/admin/v1/rooms/<room>")
|
||||||
@synapse.route("/_synapse/admin/v1/rooms/<room_id>/timestamp_to_event")
|
@synapse.route("/_synapse/admin/v1/rooms/<room>/timestamp_to_event")
|
||||||
@synapse.route("/_synapse/admin/v2/rooms/delete_status/<delete_id>")
|
@synapse.route("/_synapse/admin/v2/rooms/delete_status/<delete_id>")
|
||||||
@synapse.route("/_synapse/admin/v1/rooms/<room_id_or_alias>/make_room_admin", methods=["POST"])
|
@synapse.route("/_synapse/admin/v1/rooms/<room>/make_room_admin", methods=["POST"])
|
||||||
async def response(**kwargs):
|
async def response(**kwargs):
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
@@ -118,9 +118,24 @@ async def account_data(user_id):
|
|||||||
@synapse.route("/_synapse/admin/v1/users/<user_id>/media", methods=["GET", "DELETE"])
|
@synapse.route("/_synapse/admin/v1/users/<user_id>/media", methods=["GET", "DELETE"])
|
||||||
async def account_media(user_id):
|
async def account_media(user_id):
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
return jsonify({"media": [{"created_ts":config.the_funny_number,"last_access_ts":config.the_funny_number,"media_id":"cat","media_length":config.the_funny_number,"media_type":"image/jpeg","quarantined_by":"null","safe_from_quarantine":False,"upload_name":"cat.jpg"}], "total": config.the_funny_number})
|
return jsonify({
|
||||||
|
"media": [{
|
||||||
|
"created_ts": config.the_funny_number,
|
||||||
|
"last_access_ts": config.the_funny_number,
|
||||||
|
"media_id": "cat",
|
||||||
|
"media_length": config.the_funny_number,
|
||||||
|
"media_type": "image/jpeg",
|
||||||
|
"quarantined_by": None,
|
||||||
|
"safe_from_quarantine": False,
|
||||||
|
"upload_name": "cat.jpg"
|
||||||
|
}],
|
||||||
|
"total": config.the_funny_number
|
||||||
|
})
|
||||||
|
|
||||||
return jsonify({"deleted_media": ["cat"], "total": config.the_funny_number})
|
return jsonify({
|
||||||
|
"deleted_media": ["cat"],
|
||||||
|
"total": config.the_funny_number
|
||||||
|
})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/users/<user_id>/login", methods=["POST"])
|
@synapse.route("/_synapse/admin/v1/users/<user_id>/login", methods=["POST"])
|
||||||
async def account_login(user_id):
|
async def account_login(user_id):
|
||||||
@@ -137,7 +152,7 @@ async def device_list(user_id):
|
|||||||
"devices": [{
|
"devices": [{
|
||||||
"device_id": "VVOONNAA",
|
"device_id": "VVOONNAA",
|
||||||
"display_name": "Vona",
|
"display_name": "Vona",
|
||||||
"last_seen_ip": "127.0.0.1",
|
"last_seen_ip": config.addr,
|
||||||
"last_seen_ts": config.the_funny_number,
|
"last_seen_ts": config.the_funny_number,
|
||||||
"last_seen_user_agent": f"Vona/{globals.version}"
|
"last_seen_user_agent": f"Vona/{globals.version}"
|
||||||
}],
|
}],
|
||||||
@@ -152,7 +167,7 @@ async def device_info(user_id, device_id):
|
|||||||
return jsonify({
|
return jsonify({
|
||||||
"device_id": "VVOONNAA",
|
"device_id": "VVOONNAA",
|
||||||
"display_name": "Vona",
|
"display_name": "Vona",
|
||||||
"last_seen_ip": "127.0.0.1",
|
"last_seen_ip": config.addr,
|
||||||
"last_seen_ts": config.the_funny_number,
|
"last_seen_ts": config.the_funny_number,
|
||||||
"last_seen_user_agent": f"Vona/{globals.version}"
|
"last_seen_user_agent": f"Vona/{globals.version}"
|
||||||
})
|
})
|
||||||
@@ -169,11 +184,11 @@ async def username_available():
|
|||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/threepid/<medium>/users/<addr>")
|
@synapse.route("/_synapse/admin/v1/threepid/<medium>/users/<addr>")
|
||||||
@synapse.route("/_synapse/admin/v1/auth_providers/<provider>/users/<ext>")
|
@synapse.route("/_synapse/admin/v1/auth_providers/<provider>/users/<ext>")
|
||||||
async def threepid(p, a):
|
async def threepid(**kwargs):
|
||||||
return jsonify({"user_id": f"@vona:{config.server_name}"})
|
return jsonify({"user_id": f"@vona:{config.server_name}"})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/<user_id>/redact")
|
@synapse.route("/_synapse/admin/v1/<user_id>/redact")
|
||||||
def redact(user_id):
|
async def redact(user_id):
|
||||||
return jsonify({"redact_id": os.urandom(16).hex()})
|
return jsonify({"redact_id": os.urandom(16).hex()})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/user/redact_status/<redact_id>")
|
@synapse.route("/_synapse/admin/v1/user/redact_status/<redact_id>")
|
||||||
@@ -191,8 +206,8 @@ async def register():
|
|||||||
|
|
||||||
return jsonify({"access_token": "vona"})
|
return jsonify({"access_token": "vona"})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/join/<roomId>", methods=["POST"])
|
@synapse.route("/_synapse/admin/v1/join/<room>", methods=["POST"])
|
||||||
async def membership_manipulation(roomId):
|
async def membership_manipulation(room):
|
||||||
return jsonify({"room_id": globals.make_event_id().replace("$", "!")})
|
return jsonify({"room_id": globals.make_event_id().replace("$", "!")})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/account_validity/validity", methods=["POST"])
|
@synapse.route("/_synapse/admin/v1/account_validity/validity", methods=["POST"])
|
||||||
@@ -204,8 +219,8 @@ async def account_validity():
|
|||||||
async def server_notice(**kwargs):
|
async def server_notice(**kwargs):
|
||||||
return jsonify({"event_id": globals.make_event_id()})
|
return jsonify({"event_id": globals.make_event_id()})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/purge_history/<room_id>/<event_id>", methods=["POST"])
|
@synapse.route("/_synapse/admin/v1/purge_history/<room>/<event_id>", methods=["POST"])
|
||||||
@synapse.route("/_synapse/admin/v1/purge_history/<room_id>", methods=["POST"])
|
@synapse.route("/_synapse/admin/v1/purge_history/<room>", methods=["POST"])
|
||||||
async def purge_event(**kwargs):
|
async def purge_event(**kwargs):
|
||||||
return jsonify({"purge_id": os.urandom(16).hex()})
|
return jsonify({"purge_id": os.urandom(16).hex()})
|
||||||
|
|
||||||
@@ -213,12 +228,12 @@ async def purge_event(**kwargs):
|
|||||||
async def purge_status(purge_id):
|
async def purge_status(purge_id):
|
||||||
return jsonify({"status":"active"})
|
return jsonify({"status":"active"})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/room/<room_id>/media")
|
@synapse.route("/_synapse/admin/v1/room/<room>/media")
|
||||||
async def room_media(room_id):
|
async def room_media(room):
|
||||||
return jsonify({"local": [f"mxc://{config.server_name}/cat"], "remote": []})
|
return jsonify({"local": [f"mxc://{config.server_name}/cat"], "remote": []})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/room/<room_id>/media/quarantine", methods=["POST"])
|
@synapse.route("/_synapse/admin/v1/room/<room>/media/quarantine", methods=["POST"])
|
||||||
async def quarantine_room_media(room_id):
|
async def quarantine_room_media(room):
|
||||||
return jsonify({"num_quarantined": config.the_funny_number})
|
return jsonify({"num_quarantined": config.the_funny_number})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/media/<s>/delete", methods=["POST"])
|
@synapse.route("/_synapse/admin/v1/media/<s>/delete", methods=["POST"])
|
||||||
@@ -233,7 +248,15 @@ async def delete_remote_media():
|
|||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/statistics/users/media")
|
@synapse.route("/_synapse/admin/v1/statistics/users/media")
|
||||||
async def media_stats():
|
async def media_stats():
|
||||||
return jsonify({"users":[{"displayname":"Vona","media_count":config.the_funny_number,"media_length":config.the_funny_number,"user_id":f"@vona:{config.server_name}"}],"total":config.the_funny_number})
|
return jsonify({
|
||||||
|
"users": [{
|
||||||
|
"displayname": "Vona",
|
||||||
|
"media_count": config.the_funny_number,
|
||||||
|
"media_length": config.the_funny_number,
|
||||||
|
"user_id": f"@vona:{config.server_name}"
|
||||||
|
}],
|
||||||
|
"total": config.the_funny_number
|
||||||
|
})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/statistics/database/rooms")
|
@synapse.route("/_synapse/admin/v1/statistics/database/rooms")
|
||||||
async def room_stats():
|
async def room_stats():
|
||||||
@@ -302,7 +325,7 @@ async def interact_with_reported_event(report_id):
|
|||||||
@synapse.route("/_synapse/admin/v1/federation/destinations")
|
@synapse.route("/_synapse/admin/v1/federation/destinations")
|
||||||
async def federation_destinations():
|
async def federation_destinations():
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"destinations": [{}],
|
"destinations": [],
|
||||||
"total": 0
|
"total": 0
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -366,7 +389,7 @@ async def rooms():
|
|||||||
"total_rooms": 0
|
"total_rooms": 0
|
||||||
})
|
})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/rooms/<room_id>/members")
|
@synapse.route("/_synapse/admin/v1/rooms/<room>/members")
|
||||||
async def room_members(room):
|
async def room_members(room):
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"members": [
|
"members": [
|
||||||
@@ -375,11 +398,11 @@ async def room_members(room):
|
|||||||
"total": 1
|
"total": 1
|
||||||
})
|
})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/rooms/<room_id>/state")
|
@synapse.route("/_synapse/admin/v1/rooms/<room>/state")
|
||||||
async def room_state(room):
|
async def room_state(room):
|
||||||
return jsonify({"state": []})
|
return jsonify({"state": []})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/rooms/<room_id>/state")
|
@synapse.route("/_synapse/admin/v1/rooms/<room>/state")
|
||||||
async def room_messages(room):
|
async def room_messages(room):
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"chunk": [],
|
"chunk": [],
|
||||||
@@ -387,11 +410,11 @@ async def room_messages(room):
|
|||||||
"start": "vona"
|
"start": "vona"
|
||||||
})
|
})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/rooms/<room_id>/block", methods=["GET", "PUT"])
|
@synapse.route("/_synapse/admin/v1/rooms/<room>/block", methods=["GET", "PUT"])
|
||||||
async def block_room(room):
|
async def block_room(room):
|
||||||
return jsonify({"block": False})
|
return jsonify({"block": False})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/rooms/<room_id>", methods=["DELETE"])
|
@synapse.route("/_synapse/admin/v1/rooms/<room>", methods=["DELETE"])
|
||||||
async def room_delete(room):
|
async def room_delete(room):
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"kicked_users": [
|
"kicked_users": [
|
||||||
@@ -399,18 +422,18 @@ async def room_delete(room):
|
|||||||
],
|
],
|
||||||
"failed_to_kick_users": [],
|
"failed_to_kick_users": [],
|
||||||
"local_aliases": [],
|
"local_aliases": [],
|
||||||
"new_room_id": f"!vona:{config.server_name}"
|
"new_room_id": globals.make_event_id(seed=room)
|
||||||
})
|
})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v2/rooms/<room_id>", methods=["DELETE"])
|
@synapse.route("/_synapse/admin/v2/rooms/<room>", methods=["DELETE"])
|
||||||
async def room_delete_v2(room):
|
async def room_delete_v2(room):
|
||||||
return jsonify({"delete_id": "vona"})
|
return jsonify({"delete_id": "vona"})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v2/rooms/<room_id>/delete_status")
|
@synapse.route("/_synapse/admin/v2/rooms/<room>/delete_status")
|
||||||
async def room_delete_status(room):
|
async def room_delete_status(room):
|
||||||
return jsonify({"results": []})
|
return jsonify({"results": []})
|
||||||
|
|
||||||
@synapse.route("/_synapse/admin/v1/rooms/<room_id_or_alias>/forward_extremities", methods=["GET"])
|
@synapse.route("/_synapse/admin/v1/rooms/<room>/forward_extremities", methods=["GET"])
|
||||||
async def forward_extremities(room):
|
async def forward_extremities(room):
|
||||||
if request.method == "DELETE":
|
if request.method == "DELETE":
|
||||||
return jsonify({"deleted": 0})
|
return jsonify({"deleted": 0})
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ async def process_management(**kwargs):
|
|||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@telo.route("/_telodendria/admin/v1/privileges/<lp>", methods=["GET", "PUT", "POST", "DELETE"])
|
@telo.route("/_telodendria/admin/v1/privileges/<lp>", methods=["GET", "PUT", "POST", "DELETE"])
|
||||||
@telo.route("/_telodendria/admin/v1/privileges/", methods=["GET", "POST"])
|
@telo.route("/_telodendria/admin/v1/privileges/", methods=["GET", "POST"])
|
||||||
async def privileges(lp=None):
|
async def privileges(lp=None):
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from flask import jsonify, Response, request, send_file, abort, Blueprint
|
from flask import jsonify, Response, request, send_file, abort, Blueprint
|
||||||
import vona.globals as globals
|
import vona.globals as globals
|
||||||
from vona.config import *
|
import vona.config as config
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
@@ -24,13 +24,13 @@ def send_join(request, roomId) -> dict:
|
|||||||
create_event = {
|
create_event = {
|
||||||
"content": {
|
"content": {
|
||||||
"m.federate": True,
|
"m.federate": True,
|
||||||
"creator": f"@vona:{server_name}",
|
"creator": f"@vona:{config.server_name}",
|
||||||
"room_version": globals.room_version_from_id(roomId)
|
"room_version": globals.room_version_from_id(roomId)
|
||||||
},
|
},
|
||||||
"event_id": event_ids[0],
|
"event_id": event_ids[0],
|
||||||
"origin_server_ts": 1,
|
"origin_server_ts": 1,
|
||||||
"room_id": roomId,
|
"room_id": roomId,
|
||||||
"sender": f"@vona:{server_name}",
|
"sender": f"@vona:{config.server_name}",
|
||||||
"state_key": "",
|
"state_key": "",
|
||||||
"depth": 1,
|
"depth": 1,
|
||||||
"type": "m.room.create",
|
"type": "m.room.create",
|
||||||
@@ -44,12 +44,12 @@ def send_join(request, roomId) -> dict:
|
|||||||
our_join = {
|
our_join = {
|
||||||
"content": {
|
"content": {
|
||||||
"displayname": "Vona",
|
"displayname": "Vona",
|
||||||
"avatar_url": f"mxc://{server_name}/cat",
|
"avatar_url": f"mxc://{config.server_name}/cat",
|
||||||
"membership": "join"
|
"membership": "join"
|
||||||
},
|
},
|
||||||
"origin_server_ts": 2,
|
"origin_server_ts": 2,
|
||||||
"sender": f"@vona:{server_name}",
|
"sender": f"@vona:{config.server_name}",
|
||||||
"state_key": f"@vona:{server_name}",
|
"state_key": f"@vona:{config.server_name}",
|
||||||
"type": "m.room.member",
|
"type": "m.room.member",
|
||||||
"event_id": event_ids[1],
|
"event_id": event_ids[1],
|
||||||
"room_id": roomId,
|
"room_id": roomId,
|
||||||
@@ -70,17 +70,17 @@ def send_join(request, roomId) -> dict:
|
|||||||
pls = {
|
pls = {
|
||||||
"content": {
|
"content": {
|
||||||
"users": {
|
"users": {
|
||||||
f"@vona:{server_name}": "100"
|
f"@vona:{config.server_name}": "100"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"origin_server_ts": 3,
|
"origin_server_ts": 3,
|
||||||
"room_id": roomId,
|
"room_id": roomId,
|
||||||
"sender": f"@vona:{server_name}",
|
"sender": f"@vona:{config.server_name}",
|
||||||
"state_key": "",
|
"state_key": "",
|
||||||
"type": "m.room.power_levels",
|
"type": "m.room.power_levels",
|
||||||
"event_id": event_ids[2],
|
"event_id": event_ids[2],
|
||||||
"depth": 3,
|
"depth": 3,
|
||||||
"user_id": f"@vona:{server_name}",
|
"user_id": f"@vona:{config.server_name}",
|
||||||
"auth_events": [
|
"auth_events": [
|
||||||
[
|
[
|
||||||
screate_event["event_id"],
|
screate_event["event_id"],
|
||||||
@@ -105,7 +105,7 @@ def send_join(request, roomId) -> dict:
|
|||||||
"join_rule": "public"
|
"join_rule": "public"
|
||||||
},
|
},
|
||||||
"origin_server_ts": 4,
|
"origin_server_ts": 4,
|
||||||
"sender": f"@vona:{server_name}",
|
"sender": f"@vona:{config.server_name}",
|
||||||
"state_key": "",
|
"state_key": "",
|
||||||
"type": "m.room.join_rules",
|
"type": "m.room.join_rules",
|
||||||
"event_id": event_ids[3],
|
"event_id": event_ids[3],
|
||||||
@@ -140,7 +140,7 @@ def send_join(request, roomId) -> dict:
|
|||||||
},
|
},
|
||||||
"origin_server_ts": 5,
|
"origin_server_ts": 5,
|
||||||
"depth": 5,
|
"depth": 5,
|
||||||
"sender": f"@vona:{server_name}",
|
"sender": f"@vona:{config.server_name}",
|
||||||
"state_key": "",
|
"state_key": "",
|
||||||
"type": "m.room.guest_access",
|
"type": "m.room.guest_access",
|
||||||
"event_id": event_ids[4],
|
"event_id": event_ids[4],
|
||||||
@@ -173,7 +173,7 @@ def send_join(request, roomId) -> dict:
|
|||||||
"history_visibility": "shared"
|
"history_visibility": "shared"
|
||||||
},
|
},
|
||||||
"type": "m.room.history_visibility",
|
"type": "m.room.history_visibility",
|
||||||
"sender": f"@vona:{server_name}",
|
"sender": f"@vona:{config.server_name}",
|
||||||
"state_key": "",
|
"state_key": "",
|
||||||
"origin_server_ts": 6,
|
"origin_server_ts": 6,
|
||||||
"depth": 6,
|
"depth": 6,
|
||||||
@@ -208,7 +208,7 @@ def send_join(request, roomId) -> dict:
|
|||||||
"auth_chain": event_chain,
|
"auth_chain": event_chain,
|
||||||
"event": remote_join,
|
"event": remote_join,
|
||||||
"members_omitted": False,
|
"members_omitted": False,
|
||||||
"servers_in_room": [server_name],
|
"servers_in_room": [config.server_name],
|
||||||
"state": event_chain
|
"state": event_chain
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,10 +228,10 @@ async def version():
|
|||||||
async def keys():
|
async def keys():
|
||||||
return jsonify(globals.sign_json({
|
return jsonify(globals.sign_json({
|
||||||
"old_verify_keys": {},
|
"old_verify_keys": {},
|
||||||
"server_name": server_name,
|
"server_name": config.server_name,
|
||||||
"valid_until_ts": int(time.time() * 1000 + 604800000),
|
"valid_until_ts": int(time.time() * 1000 + 604800000),
|
||||||
"verify_keys": {
|
"verify_keys": {
|
||||||
f"ed25519:{signing_key.split()[1]}": {
|
f"ed25519:{config.signing_key.split()[1]}": {
|
||||||
"key": globals.pubkey()
|
"key": globals.pubkey()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,7 +241,7 @@ async def keys():
|
|||||||
async def room_query():
|
async def room_query():
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"room_id": globals.make_event_id().replace("$", "!"),
|
"room_id": globals.make_event_id().replace("$", "!"),
|
||||||
"servers": [server_name]
|
"servers": [config.server_name]
|
||||||
})
|
})
|
||||||
|
|
||||||
@server.route("/_matrix/federation/v1/media/download/<media_id>")
|
@server.route("/_matrix/federation/v1/media/download/<media_id>")
|
||||||
@@ -250,7 +250,7 @@ async def download_media(media_id):
|
|||||||
# multipart despite not even using
|
# multipart despite not even using
|
||||||
# it for anything. Minor annoyance.
|
# it for anything. Minor annoyance.
|
||||||
|
|
||||||
with open(cat, "rb") as img_file:
|
with open(config.cat, "rb") as img_file:
|
||||||
image_data = img_file.read()
|
image_data = img_file.read()
|
||||||
boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW"
|
boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW"
|
||||||
response_body = (
|
response_body = (
|
||||||
@@ -291,7 +291,7 @@ async def make_join(roomId, userId):
|
|||||||
}), 403
|
}), 403
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if roomId.split(":")[1] != server_name:
|
if roomId.split(":")[1] != config.server_name:
|
||||||
return not_invited()
|
return not_invited()
|
||||||
except:
|
except:
|
||||||
return not_invited()
|
return not_invited()
|
||||||
@@ -307,10 +307,10 @@ async def make_join(roomId, userId):
|
|||||||
|
|
||||||
join = {
|
join = {
|
||||||
"content": {
|
"content": {
|
||||||
"join_authorised_via_users_server": f"@vona:{server_name}",
|
"join_authorised_via_users_server": f"@vona:{config.server_name}",
|
||||||
"membership": "join"
|
"membership": "join"
|
||||||
},
|
},
|
||||||
"origin": server_name,
|
"origin": config.server_name,
|
||||||
"origin_server_ts": 7,
|
"origin_server_ts": 7,
|
||||||
"room_id": roomId,
|
"room_id": roomId,
|
||||||
"sender": userId,
|
"sender": userId,
|
||||||
@@ -344,12 +344,10 @@ async def make_join(roomId, userId):
|
|||||||
"room_version": globals.room_version_from_id(roomId)
|
"room_version": globals.room_version_from_id(roomId)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@server.route("/_matrix/federation/v1/publicRooms", methods=["POST", "GET"])
|
@server.route("/_matrix/federation/v1/publicRooms", methods=["POST", "GET"])
|
||||||
async def room_directory():
|
async def room_directory():
|
||||||
return jsonify({
|
return jsonify(globals.room_dir)
|
||||||
"chunk": [],
|
|
||||||
"total_room_count_estimate": 0
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/latest/server-server-api/#transactions
|
# https://spec.matrix.org/latest/server-server-api/#transactions
|
||||||
@@ -386,7 +384,7 @@ async def user_profile():
|
|||||||
field = request.args.get("field")
|
field = request.args.get("field")
|
||||||
if field:
|
if field:
|
||||||
if field == "avatar_url":
|
if field == "avatar_url":
|
||||||
return jsonify({"avatar_url":f"mxc://{server_name}/cat"})
|
return jsonify({"avatar_url":f"mxc://{config.server_name}/cat"})
|
||||||
elif field == "displayname":
|
elif field == "displayname":
|
||||||
return jsonify({"displayname":"Vona"})
|
return jsonify({"displayname":"Vona"})
|
||||||
|
|
||||||
@@ -395,31 +393,24 @@ async def user_profile():
|
|||||||
"error": "The requested profile key does not exist."
|
"error": "The requested profile key does not exist."
|
||||||
}), 404
|
}), 404
|
||||||
|
|
||||||
return jsonify({"avatar_url": f"mxc://{server_name}/cat","displayname": "Vona"})
|
return jsonify({"avatar_url": f"mxc://{config.server_name}/cat","displayname": "Vona"})
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/latest/server-server-api/#device-management
|
@server.route(f"/_matrix/federation/v1/user/devices/@/:{config.server_name}")
|
||||||
@server.route(f"/_matrix/federation/v1/user/devices/@/:{server_name}")
|
|
||||||
@server.route("/_matrix/federation/v1/user/devices/<user>")
|
@server.route("/_matrix/federation/v1/user/devices/<user>")
|
||||||
async def user_devices(user):
|
async def user_devices(user):
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"devices": [],
|
"devices": [],
|
||||||
"stream_id": the_funny_number,
|
"stream_id": config.the_funny_number,
|
||||||
"user_id": f"@vona:{server_name}"
|
"user_id": f"@vona:{config.server_name}"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@server.route("/_matrix/federation/v1/user/keys/query", methods=["POST"])
|
@server.route("/_matrix/federation/v1/user/keys/query", methods=["POST"])
|
||||||
async def user_keys():
|
async def user_keys():
|
||||||
try:
|
return jsonify({
|
||||||
users = request.json["device_keys"]
|
"device_keys": request.json.get("device_keys", {})
|
||||||
except:
|
})
|
||||||
return jsonify({
|
|
||||||
"errcode": "M_NOT_FOUND",
|
|
||||||
"error": "User does not exist"
|
|
||||||
}), 404
|
|
||||||
|
|
||||||
return jsonify({"device_keys": users})
|
|
||||||
|
|
||||||
|
|
||||||
@server.route("/_matrix/federation/v2/invite/<room>/<txnId>", methods=["PUT"])
|
@server.route("/_matrix/federation/v2/invite/<room>/<txnId>", methods=["PUT"])
|
||||||
@@ -429,15 +420,10 @@ async def invite_user_v2(room, txnId):
|
|||||||
|
|
||||||
@server.route("/_matrix/federation/v1/invite/<room>/<txnId>", methods=["PUT"])
|
@server.route("/_matrix/federation/v1/invite/<room>/<txnId>", methods=["PUT"])
|
||||||
async def invite_user_v1(room, txnId):
|
async def invite_user_v1(room, txnId):
|
||||||
return [200, invite_user(request.data)]
|
return [200, invite_user(request.json)]
|
||||||
|
|
||||||
|
|
||||||
def invite_user(data):
|
def invite_user(invite_data):
|
||||||
try:
|
|
||||||
invite_data = json.loads(data)
|
|
||||||
except:
|
|
||||||
return jsonify({"errcode":"M_NOT_JSON","error":"Content not JSON."}),
|
|
||||||
|
|
||||||
if "event" in invite_data:
|
if "event" in invite_data:
|
||||||
if "room_version" in invite_data:
|
if "room_version" in invite_data:
|
||||||
if invite_data["room_version"] not in ["1", "2"]:
|
if invite_data["room_version"] not in ["1", "2"]:
|
||||||
@@ -457,7 +443,7 @@ def invite_user(data):
|
|||||||
and "state_key" in event
|
and "state_key" in event
|
||||||
and "room_id" in event
|
and "room_id" in event
|
||||||
and content["membership"] == "invite"
|
and content["membership"] == "invite"
|
||||||
and event["state_key"] == f"@vona:{server_name}"
|
and event["state_key"] == f"@vona:{config.server_name}"
|
||||||
):
|
):
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"event": globals.sign_json_without_discard(invite_data["event"]),
|
"event": globals.sign_json_without_discard(invite_data["event"]),
|
||||||
@@ -477,3 +463,25 @@ async def space_hierachy(roomId):
|
|||||||
"errcode": "M_NOT_FOUND",
|
"errcode": "M_NOT_FOUND",
|
||||||
"error": "Room does not exist."
|
"error": "Room does not exist."
|
||||||
}), 404
|
}), 404
|
||||||
|
|
||||||
|
|
||||||
|
@server.route("/_matrix/federation/v1/org.matrix.msc4358/discover_common_rooms", methods=["POST"])
|
||||||
|
@server.route("/_matrix/federation/v1/discover_common_rooms", methods=["POST"])
|
||||||
|
async def discover_common_rooms():
|
||||||
|
tags = request.json.get("room_participation_tags", [])
|
||||||
|
return jsonify({"recognised_tags": tags})
|
||||||
|
|
||||||
|
|
||||||
|
@server.route("/_matrix/federation/v1/backfill/<room>")
|
||||||
|
async def backfill(room):
|
||||||
|
# TODO: burger king foot lettuce
|
||||||
|
|
||||||
|
class bullshit:
|
||||||
|
def get_json():
|
||||||
|
return {}
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"origin": config.server_name,
|
||||||
|
"origin_server_ts": int(str(time.time() * 1000).split(".")[0]),
|
||||||
|
"pdus": send_join(bullshit, room)["state"]
|
||||||
|
})
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
from resolvematrix import ServerResolver
|
||||||
|
from types import SimpleNamespace
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
import vona.config as config
|
import vona.config as config
|
||||||
import nacl.signing
|
import nacl.signing
|
||||||
@@ -9,8 +11,7 @@ import copy
|
|||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
|
||||||
version = "1.4.3"
|
version = "1.4.4"
|
||||||
http_client = httpx.Client(headers={"User-Agent": f"Vona/{version}"})
|
|
||||||
|
|
||||||
|
|
||||||
def canonical_json(value):
|
def canonical_json(value):
|
||||||
@@ -111,7 +112,9 @@ def event_hash(event_object):
|
|||||||
|
|
||||||
event_json_bytes = canonical_json(event_object)
|
event_json_bytes = canonical_json(event_object)
|
||||||
|
|
||||||
return base64.b64encode(hashlib.sha256(event_json_bytes).digest()).decode("utf-8")
|
return base64.b64encode(
|
||||||
|
hashlib.sha256(event_json_bytes).digest()
|
||||||
|
).decode("utf-8").rstrip("=")
|
||||||
|
|
||||||
|
|
||||||
def pubkey() -> str:
|
def pubkey() -> str:
|
||||||
@@ -129,7 +132,12 @@ def pubkey() -> str:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def make_auth_header(destination, method, path, content=None) -> str:
|
def make_auth_header(
|
||||||
|
destination: str,
|
||||||
|
method: str,
|
||||||
|
path: str,
|
||||||
|
content = None
|
||||||
|
) -> str:
|
||||||
request_json = {
|
request_json = {
|
||||||
"method": method,
|
"method": method,
|
||||||
"uri": path,
|
"uri": path,
|
||||||
@@ -252,3 +260,89 @@ def room_version_from_id(room_id):
|
|||||||
return most_common[0] if most_common else None
|
return most_common[0] if most_common else None
|
||||||
|
|
||||||
return most_common_character(nums)[0]
|
return most_common_character(nums)[0]
|
||||||
|
|
||||||
|
|
||||||
|
room_dir = {
|
||||||
|
"chunk": [{
|
||||||
|
"avatar_url": f"mxc://{config.server_name}/cat",
|
||||||
|
"guest_can_join": False,
|
||||||
|
"join_rule": "public",
|
||||||
|
"name": "Vona",
|
||||||
|
"num_joined_members": 1,
|
||||||
|
"room_id": make_event_id().replace("$", "!"),
|
||||||
|
"room_type": "m.room",
|
||||||
|
"topic": "",
|
||||||
|
"world_readable": False,
|
||||||
|
"via": [config.server_name]
|
||||||
|
}],
|
||||||
|
"total_room_count_estimate": 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class http_client:
|
||||||
|
http = httpx.Client(headers={"User-Agent": f"Vona/{version}"})
|
||||||
|
resolver = ServerResolver(client=http)
|
||||||
|
|
||||||
|
def _resolve(self, target) -> SimpleNamespace:
|
||||||
|
r = self.resolver.resolve(target)
|
||||||
|
|
||||||
|
if r.sni:
|
||||||
|
sni = r.sni
|
||||||
|
else:
|
||||||
|
sni = r.host_header
|
||||||
|
|
||||||
|
return SimpleNamespace(
|
||||||
|
base_url=r.base_url,
|
||||||
|
host_header=r.host_header,
|
||||||
|
sni=sni
|
||||||
|
)
|
||||||
|
|
||||||
|
def put(
|
||||||
|
self,
|
||||||
|
path: str,
|
||||||
|
destination: str,
|
||||||
|
headers: dict = {},
|
||||||
|
authorize: bool = True,
|
||||||
|
json: dict = {},
|
||||||
|
):
|
||||||
|
resolved = self._resolve(destination)
|
||||||
|
|
||||||
|
if authorize:
|
||||||
|
headers["Authorization"] = make_auth_header(
|
||||||
|
method="PUT",
|
||||||
|
destination=destination,
|
||||||
|
path=path,
|
||||||
|
)
|
||||||
|
|
||||||
|
headers["Host"] = resolved.host_header
|
||||||
|
|
||||||
|
return self.http.put(
|
||||||
|
f"{resolved.base_url}{path}",
|
||||||
|
headers=headers,
|
||||||
|
extensions={"sni_hostname": resolved.sni},
|
||||||
|
json=json
|
||||||
|
)
|
||||||
|
|
||||||
|
def get(
|
||||||
|
self,
|
||||||
|
path: str,
|
||||||
|
destination: str,
|
||||||
|
headers: dict = {},
|
||||||
|
authorize: bool = True,
|
||||||
|
):
|
||||||
|
resolved = self._resolve(destination)
|
||||||
|
|
||||||
|
if authorize:
|
||||||
|
headers["Authorization"] = make_auth_header(
|
||||||
|
method="GET",
|
||||||
|
destination=destination,
|
||||||
|
path=path,
|
||||||
|
)
|
||||||
|
|
||||||
|
headers["Host"] = resolved.host_header
|
||||||
|
|
||||||
|
return self.http.get(
|
||||||
|
f"{resolved.base_url}{path}",
|
||||||
|
headers=headers,
|
||||||
|
extensions={"sni_hostname": resolved.sni}
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
|
from resolvematrix import ServerResolver
|
||||||
|
import urllib.parse, time, json, httpx
|
||||||
import vona.globals as globals
|
import vona.globals as globals
|
||||||
import vona.config as config
|
import vona.config as config
|
||||||
import urllib.parse
|
|
||||||
import httpx
|
|
||||||
import json
|
|
||||||
import time
|
|
||||||
|
|
||||||
http_client = globals.http_client
|
http_client = globals.http_client()
|
||||||
|
|
||||||
|
|
||||||
def get_user_input(prompt):
|
def get_user_input(prompt):
|
||||||
try:
|
try:
|
||||||
return urllib.parse.quote(input(prompt).replace("\\n", "\n", count=32))
|
answer = input(prompt)
|
||||||
|
while "\\n" in answer:
|
||||||
|
answer = answer.replace("\\n", "\n")
|
||||||
|
|
||||||
|
return urllib.parse.quote(answer)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error reading input: {e}")
|
print(f"Error reading input: {e}")
|
||||||
return None
|
return None
|
||||||
@@ -21,27 +23,19 @@ room_id = get_user_input("Room ID:\n\t")
|
|||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
unresolved_server_name = input("\nServer name before resolve:\n\t")
|
server_name = input("\nServer name to join via:\n\t")
|
||||||
resolved_server_name = input("Server name after resolve:\n\t")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error reading server names: {e}")
|
print(f"Error reading server names: {e}")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
resolver = ServerResolver(client=http_client)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
make_join_auth = globals.make_auth_header(
|
|
||||||
unresolved_server_name,
|
|
||||||
"GET",
|
|
||||||
f"/_matrix/federation/v1/make_join/{room_id}/%40{username}%3A{config.server_name}?ver=1&ver=2&ver=3&ver=4&ver=5&ver=6&ver=7&ver=8&ver=9&ver=10&ver=11&ver=12",
|
|
||||||
)
|
|
||||||
|
|
||||||
print("\nSending make_join request..")
|
print("\nSending make_join request..")
|
||||||
|
|
||||||
make_join_response = http_client.get(
|
make_join_response = http_client.get(
|
||||||
f"https://{resolved_server_name}/_matrix/federation/v1/make_join/{room_id}/%40{username}%3A{config.server_name}?ver=1&ver=2&ver=3&ver=4&ver=5&ver=6&ver=7&ver=8&ver=9&ver=10&ver=11&ver=12",
|
path=f"/_matrix/federation/v1/make_join/{room_id}/%40{username}%3A{config.server_name}?ver=1&ver=2&ver=3&ver=4&ver=5&ver=6&ver=7&ver=8&ver=9&ver=10&ver=11&ver=12",
|
||||||
headers={
|
destination=server_name,
|
||||||
"Authorization": make_join_auth
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
make_join_response.raise_for_status()
|
make_join_response.raise_for_status()
|
||||||
@@ -51,7 +45,7 @@ except httpx.HTTPStatusError as e:
|
|||||||
print(f"HTTP error occurred: {e.response.status_code} - {e.response.text}")
|
print(f"HTTP error occurred: {e.response.status_code} - {e.response.text}")
|
||||||
exit(1)
|
exit(1)
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
print("Failed to decode JSON response.")
|
print("Failed to decode response.")
|
||||||
exit(1)
|
exit(1)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"An error occurred: {e}")
|
print(f"An error occurred: {e}")
|
||||||
@@ -59,7 +53,7 @@ except Exception as e:
|
|||||||
|
|
||||||
|
|
||||||
join_event = make_join.get("event", {})
|
join_event = make_join.get("event", {})
|
||||||
if make_join.get("room_version") in ["1", "2"]:
|
if make_join.get("room_version", "1") in ["1", "2"]:
|
||||||
# NOTE: if we always make it opaque than Synapse will 500 lmao
|
# NOTE: if we always make it opaque than Synapse will 500 lmao
|
||||||
join_event["event_id"] = globals.make_event_id()
|
join_event["event_id"] = globals.make_event_id()
|
||||||
|
|
||||||
@@ -72,19 +66,10 @@ except ValueError:
|
|||||||
signed_join = globals.hash_and_sign_event(join_event)
|
signed_join = globals.hash_and_sign_event(join_event)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
send_join_auth = globals.make_auth_header(
|
|
||||||
unresolved_server_name,
|
|
||||||
"PUT",
|
|
||||||
f"/_matrix/federation/v2/send_join/{room_id}/%24doesntmatter?omit_members=true",
|
|
||||||
signed_join,
|
|
||||||
)
|
|
||||||
|
|
||||||
send_join_response = http_client.put(
|
send_join_response = http_client.put(
|
||||||
f"https://{resolved_server_name}/_matrix/federation/v2/send_join/{room_id}/%24doesntmatter?omit_members=true",
|
path=f"/_matrix/federation/v2/send_join/{room_id}/%24doesntmatter?omit_members=true",
|
||||||
headers={
|
|
||||||
"Authorization": send_join_auth
|
|
||||||
},
|
|
||||||
json=signed_join,
|
json=signed_join,
|
||||||
|
destination=server_name,
|
||||||
)
|
)
|
||||||
|
|
||||||
send_join_response.raise_for_status()
|
send_join_response.raise_for_status()
|
||||||
|
|||||||
Reference in New Issue
Block a user