Make sending Matrix requests easier
This commit is contained in:
@@ -8,7 +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://foundry.fsky.io/vel/resolvematrix.git@dev",
|
"resolvematrix @ git+https://codeberg.org/timedout/resolvematrix.git",
|
||||||
]
|
]
|
||||||
|
|
||||||
authors = [
|
authors = [
|
||||||
|
|||||||
@@ -132,11 +132,9 @@ async def client():
|
|||||||
|
|
||||||
def federation_self_test():
|
def federation_self_test():
|
||||||
try:
|
try:
|
||||||
auth = globals.make_auth_header(config.server_name, "GET", "/.well-known/matrix/server")
|
resp = globals.http_client().get(
|
||||||
|
path="/",
|
||||||
resp = globals.http_client.get(
|
destination=config.server_name,
|
||||||
f"https://{config.server_name}/.well-known/matrix/server",
|
|
||||||
headers={"Authorization": auth}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
resp.raise_for_status()
|
resp.raise_for_status()
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ import vona.globals as globals
|
|||||||
import vona.config as config
|
import vona.config as config
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
||||||
hammerhead = Blueprint("hammerhead", __name__)
|
hammerhead = Blueprint("hammerhead", __name__)
|
||||||
|
|
||||||
# Hammerhead endpoints. Not documented, but code is at:
|
# Hammerhead endpoints. Not documented, but code is at:
|
||||||
# https://codeberg.org/timedout/hammerhead/src/branch/dev/hammerhead/router/routes/hammerhead
|
# https://codeberg.org/timedout/hammerhead/src/branch/dev/hammerhead/router/routes/hammerhead
|
||||||
|
|
||||||
|
|
||||||
@hammerhead.route("/_hammerhead/uptime")
|
@hammerhead.route("/_hammerhead/uptime")
|
||||||
async def uptime():
|
async def uptime():
|
||||||
return jsonify({"started_at": config.the_funny_number})
|
return jsonify({"started_at": config.the_funny_number})
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -10,7 +12,6 @@ import json
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
http_client = httpx.Client(headers={"User-Agent": f"Vona/{version}"})
|
|
||||||
|
|
||||||
|
|
||||||
def canonical_json(value):
|
def canonical_json(value):
|
||||||
@@ -131,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,
|
||||||
@@ -255,6 +261,7 @@ def room_version_from_id(room_id):
|
|||||||
|
|
||||||
return most_common_character(nums)[0]
|
return most_common_character(nums)[0]
|
||||||
|
|
||||||
|
|
||||||
room_dir = {
|
room_dir = {
|
||||||
"chunk": [{
|
"chunk": [{
|
||||||
"avatar_url": f"mxc://{config.server_name}/cat",
|
"avatar_url": f"mxc://{config.server_name}/cat",
|
||||||
@@ -270,3 +277,72 @@ room_dir = {
|
|||||||
}],
|
}],
|
||||||
"total_room_count_estimate": 1
|
"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