1.4.0
This commit is contained in:
18
TODO.md
18
TODO.md
@@ -1,18 +0,0 @@
|
|||||||
- add the entirety of Synapse Admin (higher priority to lower priority)
|
|
||||||
- [X] [Users](https://element-hq.github.io/synapse/latest/admin_api/user_admin_api.html)
|
|
||||||
- [X] [Server Version](https://element-hq.github.io/synapse/latest/admin_api/version_api.html)
|
|
||||||
- [X] [Manipulate room membership](https://element-hq.github.io/synapse/latest/admin_api/room_membership.html)
|
|
||||||
- [X] [Account validity](https://element-hq.github.io/synapse/latest/admin_api/account_validity.html)
|
|
||||||
- [X] [Server notices](https://element-hq.github.io/synapse/latest/admin_api/server_notices.html)
|
|
||||||
- [X] [Experimental features](https://element-hq.github.io/synapse/latest/admin_api/experimental_features.html)
|
|
||||||
- [X] [Register users](https://element-hq.github.io/synapse/latest/admin_api/register_api.html)
|
|
||||||
- [X] [Purge history](https://element-hq.github.io/synapse/latest/admin_api/purge_history_api.html)
|
|
||||||
- [X] [Media](https://element-hq.github.io/synapse/latest/admin_api/media_admin_api.html)
|
|
||||||
- [X] [Statistics](https://element-hq.github.io/synapse/latest/admin_api/statistics.html)
|
|
||||||
- [X] [Background updates](https://element-hq.github.io/synapse/latest/usage/administration/admin_api/background_updates.html)
|
|
||||||
- [X] [Reported events](https://element-hq.github.io/synapse/latest/admin_api/event_reports.html)
|
|
||||||
- [ ] [Federation](https://element-hq.github.io/synapse/latest/usage/administration/admin_api/federation.html)
|
|
||||||
- [ ] [Registration tokens](https://element-hq.github.io/synapse/latest/usage/administration/admin_api/registration_tokens.html)
|
|
||||||
- [ ] [Rooms](https://element-hq.github.io/synapse/latest/admin_api/rooms.html)
|
|
||||||
|
|
||||||
- implement `/_matrix/client/v1/auth_metadata`
|
|
||||||
@@ -2,7 +2,7 @@ from flask import Blueprint, jsonify
|
|||||||
from config import the_funny_number
|
from config import the_funny_number
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
apps = Blueprint("matrix_appservice", __name__)
|
apps = Blueprint("appservice", __name__)
|
||||||
|
|
||||||
# This implements both being a homeserver and
|
# This implements both being a homeserver and
|
||||||
# being an appservice. Why? Maximum carnage.
|
# being an appservice. Why? Maximum carnage.
|
||||||
@@ -10,59 +10,26 @@ apps = Blueprint("matrix_appservice", __name__)
|
|||||||
# Endpoints invoked by the homeserver are put
|
# Endpoints invoked by the homeserver are put
|
||||||
# lower than ones invoked by the appservice.
|
# lower than ones invoked by the appservice.
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/application-service-api/#pinging
|
|
||||||
# https://spec.matrix.org/v1.16/application-service-api/#pinging-1
|
|
||||||
@apps.route("/_matrix/client/v1/appservice/<app>/ping", methods=["POST"])
|
@apps.route("/_matrix/client/v1/appservice/<app>/ping", methods=["POST"])
|
||||||
async def homeserver_ping(app):
|
async def homeserver_ping(app):
|
||||||
# Sleeping here makes it more realistic
|
# Sleeping here makes it more realistic
|
||||||
await asyncio.sleep(the_funny_number / 1000)
|
await asyncio.sleep(the_funny_number / 1000)
|
||||||
return jsonify({"duration_ms": the_funny_number})
|
return jsonify({"duration_ms": the_funny_number})
|
||||||
|
|
||||||
|
|
||||||
|
@apps.route("/_matrix/client/v3/directory/list/appservice/<net>/<room>", methods=["PUT"])
|
||||||
@apps.route("/_matrix/app/v1/ping", methods=["POST"])
|
@apps.route("/_matrix/app/v1/ping", methods=["POST"])
|
||||||
async def app_ping():
|
@apps.route("/_matrix/app/v1/transactions/<txnId>", methods=["PUT"])
|
||||||
|
@apps.route("/_matrix/app/v1/thirdparty/protocol/<protocol>")
|
||||||
|
@apps.route("/_matrix/app/v1/rooms/<room>")
|
||||||
|
@apps.route("/_matrix/app/v1/users/<user>")
|
||||||
|
async def empty_dict(**kwargs):
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/application-service-api/#querying
|
@apps.route("/_matrix/app/v1/thirdparty/location")
|
||||||
@apps.route('/_matrix/app/v1/users/<user>')
|
@apps.route("/_matrix/app/v1/thirdparty/location/<protocol>")
|
||||||
async def query_user(user):
|
@apps.route("/_matrix/app/v1/thirdparty/user")
|
||||||
return jsonify({})
|
@apps.route("/_matrix/app/v1/thirdparty/user/<protocol>")
|
||||||
|
async def empty_array(**kwargs):
|
||||||
@apps.route('/_matrix/app/v1/rooms/<room>')
|
|
||||||
async def query_room(room):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/application-service-api/#pushing-events
|
|
||||||
@apps.route('/_matrix/app/v1/transactions/<txnId>', methods=['PUT'])
|
|
||||||
async def send_transaction(txnId):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/application-service-api/#third-party-networks
|
|
||||||
@apps.route('/_matrix/app/v1/thirdparty/location')
|
|
||||||
async def location():
|
|
||||||
return jsonify([])
|
return jsonify([])
|
||||||
|
|
||||||
@apps.route('/_matrix/app/v1/thirdparty/location/<protocol>')
|
|
||||||
async def location_from_protocol(protocol):
|
|
||||||
return jsonify([])
|
|
||||||
|
|
||||||
@apps.route('/_matrix/app/v1/thirdparty/protocol/<protocol>')
|
|
||||||
async def protocol_info(protocol):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@apps.route('/_matrix/app/v1/thirdparty/user')
|
|
||||||
async def thirdparty_user():
|
|
||||||
return jsonify([])
|
|
||||||
|
|
||||||
@apps.route('/_matrix/app/v1/thirdparty/user/<protocol>')
|
|
||||||
async def user_from_protocol(protocol):
|
|
||||||
return jsonify([])
|
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/application-service-api/#published-room-directories
|
|
||||||
@apps.route('/_matrix/client/v3/directory/list/appservice/<net>/<room>', methods=['PUT'])
|
|
||||||
async def publish_room(net, room):
|
|
||||||
return jsonify({})
|
|
||||||
|
|||||||
491
src/c2s.py
491
src/c2s.py
@@ -6,27 +6,100 @@ import asyncio
|
|||||||
import random
|
import random
|
||||||
import os
|
import os
|
||||||
|
|
||||||
client = Blueprint('matrix_client', __name__)
|
client = Blueprint("c2s", __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@client.route("/_matrix/client/v3/account/password", methods=["POST"])
|
||||||
|
@client.route('/_matrix/client/v3/user/<user>/account_data/<type>', methods=['GET', 'PUT'])
|
||||||
|
@client.route('/_matrix/client/r0/user/<user>/account_data/<type>', methods=['GET', 'PUT'])
|
||||||
|
@client.route('/_matrix/client/v3/sendToDevice/<event>/<txnId>', methods=["PUT"])
|
||||||
|
@client.route('/_matrix/media/v3/upload/<server>/<media>', methods=["PUT"])
|
||||||
|
@client.route('/_matrix/client/v3/thirdparty/protocols')
|
||||||
|
@client.route('/_matrix/client/r0/thirdparty/protocols')
|
||||||
|
@client.route('/_matrix/client/v3/delete_devices', methods=['POST'])
|
||||||
|
@client.route('/_matrix/client/r0/delete_devices', methods=['POST'])
|
||||||
|
@client.route('/_matrix/client/v3/logout/all', methods=['POST'])
|
||||||
|
@client.route('/_matrix/client/v3/logout', methods=['POST'])
|
||||||
|
@client.route('/_matrix/client/v3/rooms/<room>/invite', methods=['POST'])
|
||||||
|
@client.route('/_matrix/client/v3/rooms/<roomId>/leave', methods=['POST'])
|
||||||
|
@client.route('/_matrix/client/r0/rooms/<roomId>/leave', methods=['POST'])
|
||||||
|
@client.route('/_matrix/client/v3/rooms/<roomId>/read_markers', methods=['POST'])
|
||||||
|
@client.route('/_matrix/client/r0/rooms/<roomId>/read_markers', methods=['POST'])
|
||||||
|
@client.route('/_matrix/client/v3/keys/device_signing/upload', methods=['POST'])
|
||||||
|
@client.route("/_matrix/client/v3/rooms/<room>/receipt/<type>/<event>", methods=['POST'])
|
||||||
|
@client.route("/_matrix/client/v3/users/<user>/report", methods=["POST"])
|
||||||
|
@client.route('/_matrix/client/v3/voip/turnServer')
|
||||||
|
@client.route('/_matrix/client/r0/voip/turnServer')
|
||||||
|
@client.route("/_matrix/client/v3/rooms/<r>/report/<e>")
|
||||||
|
@client.route("/_matrix/client/v3/rooms/<r>/report")
|
||||||
|
@client.route("/_matrix/client/v3/users/<u>/report")
|
||||||
|
async def empty_response(**kwargs):
|
||||||
|
return jsonify({})
|
||||||
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/versions')
|
@client.route('/_matrix/client/versions')
|
||||||
def client_version():
|
async def spec_versions():
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"versions": [
|
"versions": (
|
||||||
"r0.6.0",
|
["r0.0.0"] + [f"r0.{i}.0" for i in range(1, 7)] +
|
||||||
"v1.16"
|
["r0.6.1"] + [f"v1.{i}" for i in range(1, 17)]
|
||||||
],
|
),
|
||||||
"unstable_features": {"uk.tcpip.msc4133": True}
|
"unstable_features": {
|
||||||
|
"uk.half-shot.msc2666": True,
|
||||||
|
"uk.timedout.msc4323": True
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/admin/whois/<userId>')
|
|
||||||
def admin_whois(userId):
|
|
||||||
if userId.startswith('@'):
|
|
||||||
return jsonify({"errcode":"M_MISSING_TOKEN","error":"Missing access token"})
|
|
||||||
|
|
||||||
return jsonify({"errcode":"M_INVALID_PARAM","error":"Expected UserID string to start with '@'"})
|
@client.route("/_matrix/client/v3/admin/whois/<user>")
|
||||||
|
@client.route("/_matrix/client/r0/admin/whois/<user>")
|
||||||
|
async def whois(user):
|
||||||
|
if userId.startswith("@"):
|
||||||
|
return jsonify({
|
||||||
|
"devices": {
|
||||||
|
"": {
|
||||||
|
"sessions": [{
|
||||||
|
"connections": [{
|
||||||
|
"ip": "127.0.0.1",
|
||||||
|
"last_seen": the_funny_number,
|
||||||
|
"user_agent": f"Vona/{globals.vona_version}"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"user_id": user
|
||||||
|
})
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"errcode": "M_INVALID_PARAM",
|
||||||
|
"error": "Expected UserID string to start with '@'"
|
||||||
|
})
|
||||||
|
|
||||||
|
@client.route("/_matrix/client/unstable/uk.timedout.msc4323/admin/suspend/<user>", methods=["GET", "PUT"])
|
||||||
|
@client.route("/_matrix/client/v1/admin/suspend/<user>", methods=["GET", "PUT"])
|
||||||
|
async def suspend(user):
|
||||||
|
if request.method == "PUT":
|
||||||
|
req = request.get_json()
|
||||||
|
if req and "suspended" in req:
|
||||||
|
return jsonify({"suspended": req["suspended"]})
|
||||||
|
|
||||||
|
return jsonify({"suspended": True})
|
||||||
|
|
||||||
|
|
||||||
|
@client.route("/_matrix/client/unstable/uk.timedout.msc4323/admin/lock/<user>", methods=["GET", "PUT"])
|
||||||
|
@client.route("/_matrix/client/v1/admin/lock/<user>", methods=["GET", "PUT"])
|
||||||
|
async def lock(user):
|
||||||
|
if request.method == "PUT":
|
||||||
|
req = request.get_json()
|
||||||
|
if req and "locked" in req:
|
||||||
|
return jsonify({"locked": req["locked"]})
|
||||||
|
|
||||||
|
return jsonify({"locked": True})
|
||||||
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/rooms/<roomId>/members')
|
@client.route('/_matrix/client/v3/rooms/<roomId>/members')
|
||||||
def room_member_count(roomId):
|
@client.route('/_matrix/client/r0/rooms/<roomId>/members')
|
||||||
|
async def room_member_count(roomId):
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"chunk": [{
|
"chunk": [{
|
||||||
"content": {
|
"content": {
|
||||||
@@ -44,15 +117,19 @@ def room_member_count(roomId):
|
|||||||
}]
|
}]
|
||||||
})
|
})
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/account/whoami')
|
|
||||||
def whoami():
|
@client.route("/_matrix/client/v3/account/whoami")
|
||||||
|
async def whoami():
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"device_id": "VVOONNAA",
|
"device_id": "VVOONNAA",
|
||||||
"user_id": f"@vona:{server_name}"
|
"user_id": f"@vona:{server_name}"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/register', methods=['POST'])
|
@client.route('/_matrix/client/v3/register', methods=['POST'])
|
||||||
def register():
|
@client.route('/_matrix/client/v1/register', methods=['POST'])
|
||||||
|
@client.route('/_matrix/client/r0/register', methods=['POST'])
|
||||||
|
async def register():
|
||||||
if users_can_register:
|
if users_can_register:
|
||||||
try:
|
try:
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@@ -79,8 +156,10 @@ def register():
|
|||||||
"error": "M_FORBIDDEN: Registration has been disabled."
|
"error": "M_FORBIDDEN: Registration has been disabled."
|
||||||
}), 403
|
}), 403
|
||||||
|
|
||||||
|
|
||||||
|
@client.route('/_matrix/client/r0/login', methods=['GET', 'POST'])
|
||||||
@client.route('/_matrix/client/v3/login', methods=['GET', 'POST'])
|
@client.route('/_matrix/client/v3/login', methods=['GET', 'POST'])
|
||||||
def login():
|
async def login():
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"flows": [
|
"flows": [
|
||||||
@@ -100,15 +179,17 @@ def login():
|
|||||||
})
|
})
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/account/password/email/requestToken', methods=['POST'])
|
@client.route('/_matrix/client/v3/account/password/email/requestToken', methods=['POST'])
|
||||||
def pswd_reset():
|
async def pswd_reset():
|
||||||
return jsonify({"errcode":"M_THREEPID_NOT_FOUND","error":"Email not found"}), 400
|
return jsonify({"errcode":"M_THREEPID_NOT_FOUND","error":"Email not found"}), 400
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/keys/upload', methods=['POST'])
|
@client.route('/_matrix/client/v3/keys/upload', methods=['POST'])
|
||||||
def key_upload():
|
async def key_upload():
|
||||||
return jsonify({"one_time_key_counts":{"signed_curve25519":50}})
|
return jsonify({"one_time_key_counts":{"signed_curve25519":50}})
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/room_keys/version', methods=['POST', 'GET'])
|
|
||||||
def roomkeys():
|
@client.route("/_matrix/client/v3/room_keys/version", methods=['POST', 'GET'])
|
||||||
|
@client.route("/_matrix/client/unstable/room_keys/version", methods=['POST', 'GET'])
|
||||||
|
async def room_keys():
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
return jsonify({"version": str(the_funny_number)})
|
return jsonify({"version": str(the_funny_number)})
|
||||||
|
|
||||||
@@ -128,37 +209,82 @@ def roomkeys():
|
|||||||
"version": str(the_funny_number)
|
"version": str(the_funny_number)
|
||||||
})
|
})
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/capabilities')
|
|
||||||
def capabilities():
|
|
||||||
return jsonify({"capabilities":{"m.room_versions":{"default":"2","available":{"1":"stable","2":"stable","3":"stable","4":"stable","5":"stable","6":"stable","7":"stable","8":"stable","1337":"stable","9":"stable","10":"stable","11":"stable","org.matrix.msc3757.10":"stable","org.matrix.msc3757.11":"stable"},"org.matrix.msc3244.room_capabilities":{"knock":{"preferred":"7","support":["7","8","9","10","11","org.matrix.msc3757.10","org.matrix.msc3757.11"]},"restricted":{"preferred":"9","support":["8","9","10","11","org.matrix.msc3757.10","org.matrix.msc3757.11"]}}},"m.change_password":{"enabled":True},"m.3pid_changes":{"enabled":True},"m.get_login_token":{"enabled":False},"m.profile_fields":{"enabled":True,"allowed":["*"]}}})
|
|
||||||
|
|
||||||
|
@client.route("/_matrix/client/v3/capabilities")
|
||||||
|
@client.route("/_matrix/client/r0/capabilities")
|
||||||
|
async def capabilities():
|
||||||
|
return jsonify({
|
||||||
|
"capabilities": {
|
||||||
|
"m.room_versions": {
|
||||||
|
"default": "2",
|
||||||
|
"available": {
|
||||||
|
"1": "stable",
|
||||||
|
"2": "stable",
|
||||||
|
"3": "stable",
|
||||||
|
"4": "stable",
|
||||||
|
"5": "stable",
|
||||||
|
"6": "stable",
|
||||||
|
"7": "stable",
|
||||||
|
"8": "stable",
|
||||||
|
"9": "stable",
|
||||||
|
"10": "stable",
|
||||||
|
"11": "stable",
|
||||||
|
"12": "stable"
|
||||||
|
},
|
||||||
|
"org.matrix.msc3244.room_capabilities": {
|
||||||
|
"knock": {
|
||||||
|
"preferred":"7",
|
||||||
|
"support": [
|
||||||
|
"7","8","9","10","11","12"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"restricted": {
|
||||||
|
"preferred": "9",
|
||||||
|
"support": ["8","9","10","11","12"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"m.change_password": {"enabled": True},
|
||||||
|
"m.3pid_changes": {"enabled": True},
|
||||||
|
"m.get_login_token": {"enabled": False},
|
||||||
|
"m.profile_fields": {
|
||||||
|
"enabled": True,
|
||||||
|
"allowed":["*"]
|
||||||
|
},
|
||||||
|
"account_moderation": {
|
||||||
|
"suspend": True,
|
||||||
|
"lock": True
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@client.route('/_matrix/client/r0/pushrules/')
|
||||||
@client.route('/_matrix/client/v3/pushrules/')
|
@client.route('/_matrix/client/v3/pushrules/')
|
||||||
def pushrules():
|
async def pushrules():
|
||||||
# TODO: Actually implement this
|
# TODO: Actually implement this
|
||||||
return jsonify({"errcode":"M_MISSING_TOKEN","error":"Missing access token"})
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/user/<user>/filter', methods=['POST'])
|
|
||||||
def filter(user):
|
|
||||||
return jsonify({"filter_id": "vvvooonnnaaa"})
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/user/<user>/filter/<data>')
|
|
||||||
def filter_two(user, data):
|
|
||||||
return jsonify({"filter_id": "vvvooonnnaaa"})
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/rooms/<room>/invite', methods=['POST'])
|
|
||||||
def invite_room(room):
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/knock/<room>', methods=['POST'])
|
|
||||||
def knock_room(room):
|
@client.route('/_matrix/client/v3/user/<user>/filter/<data>')
|
||||||
return jsonify({"errcode":"M_FORBIDDEN","error":"You are not allowed to knock on this room."}), 403
|
@client.route('/_matrix/client/r0/user/<user>/filter/<data>')
|
||||||
|
@client.route('/_matrix/client/v3/user/<user>/filter', methods=['POST'])
|
||||||
|
@client.route('/_matrix/client/r0/user/<user>/filter', methods=['POST'])
|
||||||
|
async def filter(**kwargs):
|
||||||
|
return jsonify({"filter_id": "vvvooonnnaaa"})
|
||||||
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/join/<room>', methods=['POST'])
|
@client.route('/_matrix/client/v3/join/<room>', methods=['POST'])
|
||||||
|
@client.route('/_matrix/client/r0/join/<room>', methods=['POST'])
|
||||||
@client.route('/_matrix/client/v3/rooms/<room>/join', methods=['POST'])
|
@client.route('/_matrix/client/v3/rooms/<room>/join', methods=['POST'])
|
||||||
def join_roomId(room):
|
@client.route('/_matrix/client/v3/knock/<room>', methods=['POST'])
|
||||||
|
async def join(room):
|
||||||
return jsonify({"room_id": room})
|
return jsonify({"room_id": room})
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/sync')
|
|
||||||
|
@client.route("/_matrix/client/v3/initialSync")
|
||||||
|
@client.route("/_matrix/client/v3/sync")
|
||||||
|
@client.route("/_matrix/client/r0/sync")
|
||||||
async def sync():
|
async def sync():
|
||||||
class bullshit:
|
class bullshit:
|
||||||
def get_json():
|
def get_json():
|
||||||
@@ -183,7 +309,10 @@ async def sync():
|
|||||||
return new_list
|
return new_list
|
||||||
|
|
||||||
room = globals.make_event_id().replace("$", "!")
|
room = globals.make_event_id().replace("$", "!")
|
||||||
old_room_state = send_join(bullshit, room)["state"]
|
old_room_state = send_join(
|
||||||
|
bullshit,
|
||||||
|
room
|
||||||
|
)["state"]
|
||||||
|
|
||||||
room_state = await remove_keys(
|
room_state = await remove_keys(
|
||||||
old_room_state,
|
old_room_state,
|
||||||
@@ -245,45 +374,64 @@ async def sync():
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/rooms/<room>/send/<eventType>/<txnId>', methods=['POST', 'PUT'])
|
@client.route('/_matrix/client/v3/rooms/<room>/send/<eventType>/<txnId>', methods=['POST', 'PUT'])
|
||||||
def send_message(room, eventType, txnId):
|
@client.route('/_matrix/client/r0/rooms/<room>/send/<eventType>/<txnId>', methods=['POST', 'PUT'])
|
||||||
|
async def send_message(room, eventType, txnId):
|
||||||
return jsonify({"event_id": globals.make_event_id()}), 200
|
return jsonify({"event_id": globals.make_event_id()}), 200
|
||||||
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/user_directory/search', methods=['POST'])
|
@client.route('/_matrix/client/v3/user_directory/search', methods=['POST'])
|
||||||
def user_directory():
|
async def user_directory():
|
||||||
return jsonify({"limited":False,"results":[{"avatar_url":f"mxc://{server_name}/cat","display_name":"Vona","user_id":f"@vona:{server_name}"}]})
|
return jsonify({
|
||||||
|
"limited": False,
|
||||||
|
"results": [{
|
||||||
|
"avatar_url": f"mxc://{server_name}/cat",
|
||||||
|
"display_name": "Vona",
|
||||||
|
"user_id": f"@vona:{server_name}"
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/devices')
|
@client.route('/_matrix/client/v3/devices')
|
||||||
def devices():
|
@client.route('/_matrix/client/r0/devices')
|
||||||
return jsonify({"devices":[{"device_id":"VVOONNAA","display_name":"Vona","last_seen_ip":"127.0.0.1","last_seen_ts":the_funny_number}]})
|
async def devices():
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/devices/<deviceId>', methods=['GET', 'PUT', 'DELETE'])
|
|
||||||
def get_device():
|
|
||||||
if request.method == 'GET':
|
|
||||||
return jsonify({"device_id": "VVOONNAA","display_name": "Vona","last_seen_ip": "127.0.0.1","last_seen_ts": the_funny_number})
|
|
||||||
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/delete_devices', methods=['POST'])
|
|
||||||
@client.route('/_matrix/client/v3/logout/all', methods=['POST'])
|
|
||||||
@client.route('/_matrix/client/v3/logout', methods=['POST'])
|
|
||||||
def delete_devices():
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/refresh', methods=['POST'])
|
|
||||||
def refresh():
|
|
||||||
return jsonify({"errcode": "M_UNKNOWN_TOKEN","error": "Soft logged out","soft_logout": True})
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/voip/turnServer')
|
|
||||||
def turnserver():
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"errcode": "M_LIMIT_EXCEEDED",
|
"devices": [{
|
||||||
"error": "Too many requests",
|
"device_id": "VVOONNAA",
|
||||||
"retry_after_ms": the_funny_number
|
"display_name": "Vona",
|
||||||
}), 429
|
"last_seen_ip": "127.0.0.1",
|
||||||
|
"last_seen_ts": the_funny_number
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@client.route('/_matrix/client/v3/devices/<device>', methods=['GET', 'PUT', 'DELETE'])
|
||||||
|
@client.route('/_matrix/client/r0/devices/<device>', methods=['GET', 'PUT', 'DELETE'])
|
||||||
|
async def get_device(device):
|
||||||
|
if request.method == "GET":
|
||||||
|
return jsonify({
|
||||||
|
"device_id": device,
|
||||||
|
"display_name": "Vona",
|
||||||
|
"last_seen_ip": "127.0.0.1",
|
||||||
|
"last_seen_ts": the_funny_number
|
||||||
|
})
|
||||||
|
|
||||||
|
return jsonify({})
|
||||||
|
|
||||||
|
|
||||||
|
@client.route("/_matrix/client/v3/refresh", methods=['POST'])
|
||||||
|
async def refresh():
|
||||||
|
return jsonify({
|
||||||
|
"access_token": "vona",
|
||||||
|
"expires_in_ms": the_funny_number * 1000,
|
||||||
|
"refresh_token": "vona"
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/unstable/im.nheko.summary/rooms/<roomId>/summary')
|
@client.route('/_matrix/client/unstable/im.nheko.summary/rooms/<roomId>/summary')
|
||||||
@client.route('/_matrix/client/unstable/im.nheko.summary/summary/<roomId>')
|
@client.route('/_matrix/client/unstable/im.nheko.summary/summary/<roomId>')
|
||||||
|
@client.route('/_matrix/client/v1/room_summary/<roomId>')
|
||||||
def unstable_room_summary(roomId):
|
def unstable_room_summary(roomId):
|
||||||
room = room_dir_room['chunk'][0]
|
room = room_dir_room['chunk'][0]
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -300,59 +448,93 @@ def unstable_room_summary(roomId):
|
|||||||
"room_version": 2,
|
"room_version": 2,
|
||||||
})
|
})
|
||||||
|
|
||||||
@client.route('/_matrix/client/v1/room_summary/<roomId>')
|
|
||||||
def room_summary(roomId):
|
|
||||||
room = room_dir_room['chunk'][0]
|
|
||||||
return jsonify({
|
|
||||||
"room_id": room['room_id'],
|
|
||||||
"avatar_url": room['avatar_url'],
|
|
||||||
"guest_can_join": room['guest_can_join'],
|
|
||||||
"name": room['name'],
|
|
||||||
"num_joined_members": room['num_joined_members'],
|
|
||||||
"topic": room['topic'],
|
|
||||||
"world_readable": room['world_readable'],
|
|
||||||
"join_rule": room['join_rule'],
|
|
||||||
"room_type": room['room_type'],
|
|
||||||
"membership": "join",
|
|
||||||
"room_version": 2,
|
|
||||||
})
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/r0/directory/room/<roomId>')
|
@client.route("/_matrix/client/v3/directory/room/<room>", methods=["GET", "PUT", "DELETE"])
|
||||||
def r0_room_query(roomId):
|
@client.route("/_matrix/client/r0/directory/room/<room>")
|
||||||
|
async def room_query(room):
|
||||||
|
if request.method == "GET":
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"room_id": room_dir_room['chunk'][0]['room_id'],
|
"room_id": room_dir_room['chunk'][0]['room_id'],
|
||||||
"servers": [server_name]
|
"servers": [server_name]
|
||||||
})
|
})
|
||||||
|
|
||||||
@client.route('/_matrix/client/r0/directory/list/room/<roomId>')
|
return jsonify({})
|
||||||
def r0_room_vis(roomId):
|
|
||||||
|
@client.route("/_matrix/client/v3/rooms/<room>/aliases")
|
||||||
|
async def room_aliases(room):
|
||||||
|
return jsonify({
|
||||||
|
"aliases": [
|
||||||
|
f"#vona:{server_name}"
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@client.route("/_matrix/client/v3/directory/list/room/<room>", methods=["GET", "PUT"])
|
||||||
|
@client.route('/_matrix/client/r0/directory/list/room/<room>', methods=["GET", "PUT"])
|
||||||
|
async def room_visibility(room):
|
||||||
return jsonify({"visibility": "public"})
|
return jsonify({"visibility": "public"})
|
||||||
|
|
||||||
@client.route('/_matrix/client/r0/publicRooms')
|
@client.route("/_matrix/client/v3/search", methods=["POST"])
|
||||||
def r0_room_directory():
|
async def search():
|
||||||
return jsonify(room_dir_room)
|
room = globals.make_event_id().replace("$", "!")
|
||||||
|
event = globals.make_event_id()
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"search_categories": {
|
||||||
|
"room_events": {
|
||||||
|
"count": 1,
|
||||||
|
"groups": {
|
||||||
|
"room_id": {
|
||||||
|
room: {
|
||||||
|
"next_batch": "vona",
|
||||||
|
"order": 1,
|
||||||
|
"results": [event]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"highlights": [],
|
||||||
|
"next_batch": "vona",
|
||||||
|
"results": [{
|
||||||
|
"rank": the_funny_number,
|
||||||
|
"result": {
|
||||||
|
"content": {
|
||||||
|
"msgtype": "m.text",
|
||||||
|
"body": "Number 15: Burger King Foot Lettuce.\nThe last thing you'd want in your Burger King burger is someones foot fungus, but as it turns out, that might be what you get. A 4channer uploaded a photo, anonymously to the site showcasing his feet in a plastic bin of lettuce with the statement \"This is the lettuce you eat at Burger King.\". Admittedly, he had shoes on, but thats even worse. The post went live at 11:38 PM on July 16 and a mere 20 minutes later the Burger King in question was alerted to the rogue employee. At least, I hope hes rogue. How did it happen? Well, the BK employee hadn't removed the EXIF data from the uploaded photo, which suggested that the culprit was somewhere in Mayfield Heights, Ohio. This was at 11:47. 3 minutes later, at 11:50, the Burger King branch was posted with wishes of happy unemployment. 5 minutes later, the news station was contacted by another 4channer, and 3 minutes later at 11:58 a link was posted: BK's tell us about us online forum. The foot photo, otherwise known as Exhibit A, was attached. Cleveland Seen Magazine contacted the BK in question and the next day when questioned, the breakfast shift manager said \"Oh, I know who that is, hes getting fired\". Mystery solved, by 4chan. Now we can go back to eating our fast food in peace.",
|
||||||
|
"format": "org.matrix.custom.html",
|
||||||
|
"formatted_body": "Number 15: Burger King Foot Lettuce.<br />The last thing you'd want in your Burger King burger is someones foot fungus, but as it turns out, that might be what you get. A 4channer uploaded a photo, anonymously to the site showcasing his feet in a plastic bin of lettuce with the statement "This is the lettuce you eat at Burger King.". Admittedly, he had shoes on, but thats even worse. The post went live at 11:38 PM on July 16 and a mere 20 minutes later the Burger King in question was alerted to the rogue employee. At least, I hope hes rogue. How did it happen? Well, the BK employee hadn't removed the EXIF data from the uploaded photo, which suggested that the culprit was somewhere in Mayfield Heights, Ohio. This was at 11:47. 3 minutes later, at 11:50, the Burger King branch was posted with wishes of happy unemployment. 5 minutes later, the news station was contacted by another 4channer, and 3 minutes later at 11:58 a link was posted: BK's tell us about us online forum. The foot photo, otherwise known as Exhibit A, was attached. Cleveland Seen Magazine contacted the BK in question and the next day when questioned, the breakfast shift manager said "Oh, I know who that is, hes getting fired". Mystery solved, by 4chan. Now we can go back to eating our fast food in peace."
|
||||||
|
},
|
||||||
|
"event_id": event,
|
||||||
|
"origin_server_ts": the_funny_number,
|
||||||
|
"room_id": room,
|
||||||
|
"sender": f"@vona:{server_name}",
|
||||||
|
"type": "m.room.message"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
@client.route('/_matrix/media/v1/thumbnail/<server>/<file>')
|
@client.route('/_matrix/media/v1/thumbnail/<server>/<file>')
|
||||||
@client.route('/_matrix/client/v1/media/thumbnail/<s>/<f>')
|
@client.route('/_matrix/client/v1/media/thumbnail/<s>/<f>')
|
||||||
@client.route('/_matrix/media/r0/thumbnail/<server>/<file>')
|
@client.route('/_matrix/media/r0/thumbnail/<server>/<file>')
|
||||||
def media(server, file):
|
@client.route('/_matrix/media/v3/thumbnail/<server>/<media>')
|
||||||
|
@client.route('/_matrix/media/v3/download/<server>/<media>/<file>')
|
||||||
|
@client.route('/_matrix/client/v1/media/download/<s>/<f>')
|
||||||
|
@client.route('/_matrix/media/v3/download/<server>/<media>')
|
||||||
|
@client.route('/_matrix/media/r0/download/<server>/<media>')
|
||||||
|
async def media(**kwargs):
|
||||||
return send_file(cat)
|
return send_file(cat)
|
||||||
|
|
||||||
@client.route('/_matrix/client/r0/admin/whois/<userId>')
|
|
||||||
def whois(userId):
|
|
||||||
return jsonify({"user_id":f"@vona:{server_name}","devices":{"":{"sessions":[{"connections":[{"ip":f"{the_funny_number}.{the_funny_number}.{the_funny_number}.{the_funny_number}","last_seen":the_funny_number,"user_agent":f"Vona/{the_funny_number}.0"},{"ip":f"{the_funny_number}.{the_funny_number}.{the_funny_number}.{the_funny_number}","last_seen":the_funny_number,"user_agent":f"Vona/{the_funny_number}.0"}]}]}}})
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/register/available')
|
@client.route('/_matrix/client/v3/register/available')
|
||||||
@client.route('/_matrix/client/r0/register/available')
|
@client.route('/_matrix/client/r0/register/available')
|
||||||
def username_available():
|
async def username_available():
|
||||||
return jsonify({"available": True})
|
return jsonify({"available": True})
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/thirdparty/protocols')
|
|
||||||
def thirdparty_protocols():
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@client.route('/_matrix/media/v3/preview_url')
|
@client.route('/_matrix/media/v3/preview_url')
|
||||||
def url_preview():
|
async def url_preview():
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"matrix:image:size": 102400,
|
"matrix:image:size": 102400,
|
||||||
"og:description": "look at this cool cat",
|
"og:description": "look at this cool cat",
|
||||||
@@ -364,49 +546,28 @@ def url_preview():
|
|||||||
})
|
})
|
||||||
|
|
||||||
@client.route('/_matrix/client/v1/media/preview_url')
|
@client.route('/_matrix/client/v1/media/preview_url')
|
||||||
def media_preview():
|
async def media_preview():
|
||||||
response = send_file(cat)
|
response = send_file(cat)
|
||||||
response.headers['Content-Disposition'] = f'inline; filename="cat.jpg"'
|
response.headers['Content-Disposition'] = f'inline; filename="cat.jpg"'
|
||||||
response.headers['Content-Type'] = 'image/jpg'
|
response.headers['Content-Type'] = 'image/jpg'
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@client.route('/_matrix/media/v1/create', methods=['POST'])
|
|
||||||
def create_mxc():
|
|
||||||
return jsonify({"content_uri": f"mxc://{server_name}/cat"})
|
|
||||||
|
|
||||||
@client.route('/_matrix/media/v3/upload', methods=['POST'])
|
@client.route('/_matrix/media/v3/upload', methods=['POST'])
|
||||||
def upload_media():
|
@client.route('/_matrix/media/r0/upload', methods=['POST'])
|
||||||
|
@client.route('/_matrix/media/v1/create', methods=['POST'])
|
||||||
|
async def upload_media():
|
||||||
return jsonify({"content_uri": f"mxc://{server_name}/cat"})
|
return jsonify({"content_uri": f"mxc://{server_name}/cat"})
|
||||||
|
|
||||||
@client.route('/_matrix/media/v3/upload/<server>/<media>', methods=['PUT'])
|
|
||||||
def upload_media_to_mxc(server, media):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@client.route('/_matrix/media/v3/config')
|
@client.route('/_matrix/media/v3/config')
|
||||||
def media_config():
|
async def media_config():
|
||||||
return jsonify({"m.upload.size": the_funny_number})
|
return jsonify({"m.upload.size": the_funny_number * 69420})
|
||||||
|
|
||||||
@client.route('/_matrix/media/v3/download/<server>/<media>')
|
|
||||||
def v3_download_media(server, media):
|
|
||||||
return send_file(cat)
|
|
||||||
|
|
||||||
@client.route('/_matrix/media/v3/download/<server>/<media>/<file>')
|
|
||||||
def v3_download_file(server, media, file):
|
|
||||||
return send_file(cat)
|
|
||||||
|
|
||||||
@client.route('/_matrix/media/v3/thumbnail/<server>/<media>')
|
|
||||||
def v3_thumbnail_media(server, media):
|
|
||||||
return send_file(cat)
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/sendToDevice/<event>/<txnId>', methods=['PUT'])
|
|
||||||
def send_to_device(event, txnId):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/profile/<userId>/<key>', methods=['GET', 'PUT', 'DELETE'])
|
@client.route('/_matrix/client/v3/profile/<userId>/<key>', methods=['GET', 'PUT', 'DELETE'])
|
||||||
def user_profile_keys(userId, key):
|
@client.route('/_matrix/client/r0/profile/<userId>/<key>', methods=['GET', 'PUT', 'DELETE'])
|
||||||
if request.method == 'PUT' or request.method == 'DELETE':
|
async def profile_keys(userId, key):
|
||||||
return jsonify({})
|
if request.method == 'GET':
|
||||||
elif request.method == 'GET':
|
|
||||||
if key == 'avatar_url':
|
if key == 'avatar_url':
|
||||||
return jsonify({"avatar_url": f"mxc://{server_name}/cat"})
|
return jsonify({"avatar_url": f"mxc://{server_name}/cat"})
|
||||||
elif key == 'displayname':
|
elif key == 'displayname':
|
||||||
@@ -417,12 +578,20 @@ def user_profile_keys(userId, key):
|
|||||||
"error": "The requested profile key does not exist."
|
"error": "The requested profile key does not exist."
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return jsonify({})
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/profile/<userId>')
|
@client.route('/_matrix/client/v3/profile/<userId>')
|
||||||
def user_profile(userId):
|
@client.route('/_matrix/client/r0/profile/<userId>')
|
||||||
return jsonify({"avatar_url":f"mxc://{server_name}/cat","displayname":"Vona"})
|
async def user_profile(userId):
|
||||||
|
return jsonify({
|
||||||
|
"avatar_url": f"mxc://{server_name}/cat",
|
||||||
|
"displayname": "Vona"
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/rooms/<roomId>/messages')
|
@client.route('/_matrix/client/v3/rooms/<roomId>/messages')
|
||||||
def room_messages(roomId):
|
@client.route('/_matrix/client/r0/rooms/<roomId>/messages')
|
||||||
|
async def room_messages(roomId):
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"chunk": [{
|
"chunk": [{
|
||||||
"content": {
|
"content": {
|
||||||
@@ -441,29 +610,39 @@ def room_messages(roomId):
|
|||||||
"start": f"{os.urandom(16).hex()}"
|
"start": f"{os.urandom(16).hex()}"
|
||||||
})
|
})
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/rooms/<roomId>/leave', methods=['POST'])
|
|
||||||
def leave_room(roomId):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/rooms/<roomId>/read_markers', methods=['POST'])
|
|
||||||
def read_markers(roomId):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/user/<user>/account_data/<type>', methods=['PUT'])
|
|
||||||
async def set_custom_account_data(user, type):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/keys/device_signing/upload', methods=['POST'])
|
|
||||||
async def upload_device_signing_keys():
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@client.route('/_matrix/client/v3/keys/query', methods=['POST'])
|
@client.route('/_matrix/client/v3/keys/query', methods=['POST'])
|
||||||
|
@client.route('/_matrix/client/r0/keys/query', methods=['POST'])
|
||||||
async def query_keys():
|
async def query_keys():
|
||||||
# Should be replaced eventually
|
# Should be replaced eventually
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
@client.route("/_matrix/client/api/v1/createRoom", methods=["POST"])
|
||||||
|
@client.route("/_matrix/client/v3/createRoom", methods=["POST"])
|
||||||
|
@client.route("/_matrix/client/r0/createRoom", methods=["POST"])
|
||||||
|
async def create_room():
|
||||||
|
return jsonify({"room_id": room_dir_room["chunk"][0]["room_id"]})
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/client-server-api/#post_matrixclientv3roomsroomidreceiptreceipttypeeventid
|
|
||||||
@client.route("/_matrix/client/v3/rooms/<room>/receipt/<type>/<event>", methods=['POST'])
|
@client.route("/_matrix/client/unstable/uk.half-shot.msc2666/mutual_rooms")
|
||||||
def send_read_receipt(room, type, event):
|
@client.route("/_matrix/client/v1/user/mutual_rooms")
|
||||||
|
async def mutual_rooms():
|
||||||
|
return jsonify({
|
||||||
|
"joined": [
|
||||||
|
room_dir_room["chunk"][0]["room_id"]
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@client.route("/_matrix/client/r0/presence/<user>/status", methods=["GET", "PUT"])
|
||||||
|
async def presence(user):
|
||||||
|
if request.method == "PUT":
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"presence": "online"
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@client.route('/_matrix/client/r0/publicRooms', methods=["GET", "POST"])
|
||||||
|
async def room_directory():
|
||||||
|
return jsonify(room_dir_room)
|
||||||
|
|||||||
375
src/custom.py
375
src/custom.py
@@ -5,7 +5,7 @@ import base64
|
|||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
|
||||||
custom = Blueprint('matrix_custom', __name__)
|
custom = Blueprint("custom", __name__)
|
||||||
|
|
||||||
# This implements custom endpoints
|
# This implements custom endpoints
|
||||||
# used by other homeserver
|
# used by other homeserver
|
||||||
@@ -16,6 +16,29 @@ custom = Blueprint('matrix_custom', __name__)
|
|||||||
# files eventually.
|
# files eventually.
|
||||||
|
|
||||||
|
|
||||||
|
@custom.route('/_synapse/admin/v1/suspend/<user_id>', methods=["PUT"])
|
||||||
|
@custom.route('/_synapse/admin/v1/deactivate/<user_id>', methods=['POST'])
|
||||||
|
@custom.route('/_synapse/admin/v1/reset_password/<user_id>', methods=['POST'])
|
||||||
|
@custom.route('/_synapse/admin/v1/users/<user_id>/admin', methods=["PUT"])
|
||||||
|
@custom.route('/_synapse/admin/v2/users/<user_id>/delete_devices', methods=['POST'])
|
||||||
|
@custom.route('/_synapse/admin/v1/users/<user_id>/shadow_ban', methods=['DELETE', 'POST'])
|
||||||
|
@custom.route('/_synapse/admin/v1/users/<user_id>/override_ratelimit', methods=['GET', 'POST', 'DELETE'])
|
||||||
|
@custom.route('/_synapse/admin/v1/media/protect/<media_id>', methods=['POST'])
|
||||||
|
@custom.route('/_synapse/admin/v1/media/unprotect/<media_id>', methods=['POST'])
|
||||||
|
@custom.route('/_synapse/admin/v1/media/quarantine/<server_name>/<media_id>', methods=['POST'])
|
||||||
|
@custom.route('/_synapse/admin/v1/media/unquarantine/<server_name>/<media_id>', methods=['POST'])
|
||||||
|
@custom.route('/_dendrite/admin/purgeRoom/<roomId>', methods=['POST'])
|
||||||
|
@custom.route('/_dendrite/admin/refreshDevices/<userId>', methods=['POST'])
|
||||||
|
@custom.route('/_dendrite/admin/fulltext/reindex')
|
||||||
|
@custom.route("/_synapse/admin/v1/federation/destinations/<destination>/reset_connection", methods=["POST"])
|
||||||
|
@custom.route("/_synapse/admin/v1/rooms/<room>")
|
||||||
|
@custom.route("/_synapse/admin/v1/rooms/<room_id>/timestamp_to_event")
|
||||||
|
@custom.route("/_synapse/admin/v2/rooms/delete_status/<delete_id>")
|
||||||
|
@custom.route("/_synapse/admin/v1/rooms/<room_id_or_alias>/make_room_admin", methods=["POST"])
|
||||||
|
async def empty_response(**kwargs):
|
||||||
|
return jsonify({})
|
||||||
|
|
||||||
|
|
||||||
# Synapse
|
# Synapse
|
||||||
@custom.route('/_synapse/admin/v1/server_version')
|
@custom.route('/_synapse/admin/v1/server_version')
|
||||||
def synapse_version():
|
def synapse_version():
|
||||||
@@ -50,31 +73,28 @@ def synapse_user_info(user_id):
|
|||||||
return jsonify({}), 201
|
return jsonify({}), 201
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/whois/<user_id>')
|
@custom.route('/_synapse/admin/v1/whois/<user_id>')
|
||||||
def synapse_whois(user_id):
|
async def synapse_whois(user_id):
|
||||||
return jsonify({"user_id":f"@vona:{server_name}","devices":{"":{"sessions":[{"connections":[{"ip":f"{the_funny_number}.{the_funny_number}.{the_funny_number}.{the_funny_number}","last_seen":the_funny_number,"user_agent":f"Vona/{vona_version}"},{"ip":f"{the_funny_number}.{the_funny_number}.{the_funny_number}.{the_funny_number}","last_seen":the_funny_number,"user_agent":f"Vona/{vona_version}"}]}]}}})
|
return jsonify({
|
||||||
|
"user_id": f"@vona:{server_name}",
|
||||||
@custom.route('/_synapse/admin/v1/deactivate/<user_id>', methods=['POST'])
|
"devices": {
|
||||||
def synapse_deactivate(user_id):
|
"": {
|
||||||
return jsonify({})
|
"sessions": [{
|
||||||
|
"connections": [{
|
||||||
@custom.route('/_synapse/admin/v1/suspend/<user_id>', methods=['PUT'])
|
"ip":f"127.0.0.1",
|
||||||
def synapse_suspend(user_id):
|
"last_seen":the_funny_number,
|
||||||
return jsonify({})
|
"user_agent":f"Vona/{vona_version}"
|
||||||
|
}]
|
||||||
@custom.route('/_synapse/admin/v1/reset_password/<user_id>', methods=['POST'])
|
}]
|
||||||
def synapse_reset_pswd(user_id):
|
}
|
||||||
return jsonify({})
|
}
|
||||||
|
})
|
||||||
@custom.route('/_synapse/admin/v1/users/<user_id>/admin', methods=['PUT'])
|
|
||||||
def synapse_change_admin(user_id):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/users/<user_id>/joined_rooms')
|
@custom.route('/_synapse/admin/v1/users/<user_id>/joined_rooms')
|
||||||
def synapse_user_joined_rooms(user_id):
|
def synapse_user_joined_rooms(user_id):
|
||||||
return jsonify({"joined_rooms":[room_dir_room['chunk'][0]['room_id']],"total":1})
|
return jsonify({"joined_rooms":[room_dir_room['chunk'][0]['room_id']],"total":1})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/users/<user_id>/sent_invite_count')
|
@custom.route('/_synapse/admin/v1/users/<user_id>/sent_invite_count')
|
||||||
def synapse_invite_count(user_id):
|
async def synapse_invite_count(user_id):
|
||||||
return jsonify({"invite_count": the_funny_number})
|
return jsonify({"invite_count": the_funny_number})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/users/<user_id>/accountdata')
|
@custom.route('/_synapse/admin/v1/users/<user_id>/accountdata')
|
||||||
@@ -99,43 +119,43 @@ def synapse_stupid_mas_bullshit(user_id):
|
|||||||
@custom.route('/_synapse/admin/v2/users/<user_id>/devices', methods=['GET', 'POST'])
|
@custom.route('/_synapse/admin/v2/users/<user_id>/devices', methods=['GET', 'POST'])
|
||||||
def synapse_device_list(user_id):
|
def synapse_device_list(user_id):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return jsonify({"devices":[{"device_id":"VVOONNAA","display_name":"Vona","last_seen_ip":"127.0.0.1","last_seen_ts":the_funny_number, "last_seen_user_agent": f"Vona/{vona_version}"}], "total": the_funny_number})
|
return jsonify({
|
||||||
|
"devices": [{
|
||||||
|
"device_id": "VVOONNAA",
|
||||||
|
"display_name": "Vona",
|
||||||
|
"last_seen_ip": "127.0.0.1",
|
||||||
|
"last_seen_ts": the_funny_number,
|
||||||
|
"last_seen_user_agent": f"Vona/{vona_version}"
|
||||||
|
}],
|
||||||
|
"total": 1
|
||||||
|
})
|
||||||
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v2/users/<user_id>/delete_devices', methods=['POST'])
|
@custom.route('/_synapse/admin/v2/users/<user_id>/devices/<device_id>', methods=["GET", "PUT", "DELETE"])
|
||||||
def synapse_delete_devices(user_id):
|
async def synapse_device_info(user_id, device_id):
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v2/users/<user_id>/devices/<device_id>')
|
|
||||||
def synapse_device_info(user_id, device_id):
|
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return jsonify({"device_id":"VVOONNAA","display_name":"Vona","last_seen_ip":"127.0.0.1","last_seen_ts":the_funny_number, "last_seen_user_agent": f"Vona/{vona_version}"})
|
return jsonify({
|
||||||
|
"device_id": "VVOONNAA",
|
||||||
|
"display_name": "Vona",
|
||||||
|
"last_seen_ip": "127.0.0.1",
|
||||||
|
"last_seen_ts": the_funny_number,
|
||||||
|
"last_seen_user_agent": f"Vona/{vona_version}"
|
||||||
|
})
|
||||||
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/users/<user_id>/pushers')
|
@custom.route('/_synapse/admin/v1/users/<user_id>/pushers')
|
||||||
def synapse_pushers(user_id):
|
async def synapse_pushers(user_id):
|
||||||
return jsonify({"pushers": [], "total": the_funny_number})
|
return jsonify({"pushers": [], "total": the_funny_number})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/users/<user_id>/shadow_ban', methods=['DELETE', 'POST'])
|
|
||||||
def synapse_shadow_ban(user_id):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/users/<user_id>/override_ratelimit', methods=['GET', 'POST', 'DELETE'])
|
|
||||||
def synapse_override_ratelimit(user_id):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/username_available')
|
@custom.route('/_synapse/admin/v1/username_available')
|
||||||
def synapse_username_available():
|
async def synapse_username_available():
|
||||||
return jsonify({"available": True})
|
return jsonify({"available": True})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/auth_providers/<provider>/users/<ext>')
|
|
||||||
def synapse_auth_providers(provider, ext):
|
|
||||||
return jsonify({"user_id": f"@vona:{server_name}"})
|
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/threepid/<medium>/users/<addr>')
|
@custom.route('/_synapse/admin/v1/threepid/<medium>/users/<addr>')
|
||||||
def synapse_threepid(medium, addr):
|
@custom.route('/_synapse/admin/v1/auth_providers/<provider>/users/<ext>')
|
||||||
|
async def synapse_threepid(p, a):
|
||||||
return jsonify({"user_id": f"@vona:{server_name}"})
|
return jsonify({"user_id": f"@vona:{server_name}"})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/<user_id>/redact')
|
@custom.route('/_synapse/admin/v1/<user_id>/redact')
|
||||||
@@ -143,42 +163,36 @@ def synapse_redact(user_id):
|
|||||||
return jsonify({"redact_id": os.urandom(16).hex()})
|
return jsonify({"redact_id": os.urandom(16).hex()})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/user/redact_status/<redact_id>')
|
@custom.route('/_synapse/admin/v1/user/redact_status/<redact_id>')
|
||||||
def synapse_redact_status(redact_id):
|
async def synapse_redact_status(redact_id):
|
||||||
return jsonify({"status":"active","failed_redactions":[]})
|
return jsonify({"status":"active","failed_redactions":[]})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/experimental_features/<user_id>', methods=['GET', 'PUT'])
|
@custom.route('/_synapse/admin/v1/experimental_features/<user_id>', methods=['GET', 'PUT'])
|
||||||
def synapse_experimental_features(user_id):
|
async def synapse_experimental_features(user_id):
|
||||||
return jsonify({"features": {}})
|
return jsonify({"features": {}})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/register', methods=['GET', 'POST'])
|
@custom.route('/_synapse/admin/v1/register', methods=['GET', 'POST'])
|
||||||
def synapse_register():
|
async def synapse_register():
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return jsonify({"nonce": os.urandom(16).hex()})
|
return jsonify({"nonce": os.urandom(16).hex()})
|
||||||
|
|
||||||
return jsonify({"access_token": f"@vona:{server_name}"})
|
return jsonify({"access_token": "vona"})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/join/<roomId>', methods=['POST'])
|
@custom.route('/_synapse/admin/v1/join/<roomId>', methods=['POST'])
|
||||||
def synapse_membership_manipulation(roomId):
|
async def synapse_membership_manipulation(roomId):
|
||||||
return jsonify({"room_id": room_dir_room['chunk'][0]['room_id']})
|
return jsonify({"room_id": room_dir_room['chunk'][0]['room_id']})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/account_validity/validity', methods=['POST'])
|
@custom.route('/_synapse/admin/v1/account_validity/validity', methods=['POST'])
|
||||||
def synapse_account_validity():
|
async def synapse_account_validity():
|
||||||
return jsonify({"expiration_ts": the_funny_number})
|
return jsonify({"expiration_ts": the_funny_number})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/send_server_notice', methods=['POST'])
|
@custom.route('/_synapse/admin/v1/send_server_notice', methods=['POST'])
|
||||||
def synapse_server_notice():
|
@custom.route('/_synapse/admin/v1/send_server_notice/<txnId>', methods=["PUT"])
|
||||||
|
async def synapse_server_notice(**kwargs):
|
||||||
return jsonify({"event_id": make_event_id()})
|
return jsonify({"event_id": make_event_id()})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/send_server_notice/<txnId>', methods=['PUT'])
|
|
||||||
def synapse_server_notice_second(txnId):
|
|
||||||
return jsonify({"event_id": make_event_id()})
|
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/purge_history/<room_id>', methods=['POST'])
|
|
||||||
def synapse_purge_room_history(room_id):
|
|
||||||
return jsonify({"purge_id": os.urandom(16).hex()})
|
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/purge_history/<room_id>/<event_id>', methods=['POST'])
|
@custom.route('/_synapse/admin/v1/purge_history/<room_id>/<event_id>', methods=['POST'])
|
||||||
def synapse_purge_event(room_id, event_id):
|
@custom.route('/_synapse/admin/v1/purge_history/<room_id>', methods=['POST'])
|
||||||
|
async def synapse_purge_event(**kwargs):
|
||||||
return jsonify({"purge_id": os.urandom(16).hex()})
|
return jsonify({"purge_id": os.urandom(16).hex()})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/purge_history_status/<purge_id>')
|
@custom.route('/_synapse/admin/v1/purge_history_status/<purge_id>')
|
||||||
@@ -189,122 +203,215 @@ def synapse_purge_status(purge_id):
|
|||||||
def synapse_room_media(room_id):
|
def synapse_room_media(room_id):
|
||||||
return jsonify({"local": [f"mxc://{server_name}/cat"], "remote": []})
|
return jsonify({"local": [f"mxc://{server_name}/cat"], "remote": []})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/media/quarantine/<server_name>/<media_id>', methods=['POST'])
|
|
||||||
def synapse_quarantine_media(server_name, media_id):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/media/unquarantine/<server_name>/<media_id>', methods=['POST'])
|
|
||||||
def synapse_unquarantine_media(server_name, media_id):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/room/<room_id>/media/quarantine', methods=['POST'])
|
@custom.route('/_synapse/admin/v1/room/<room_id>/media/quarantine', methods=['POST'])
|
||||||
def synapse_quarantine_room_media(room_id):
|
def synapse_quarantine_room_media(room_id):
|
||||||
return jsonify({"num_quarantined": the_funny_number})
|
return jsonify({"num_quarantined": the_funny_number})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/media/protect/<media_id>', methods=['POST'])
|
|
||||||
def synapse_protect_media(media_id):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/media/unprotect/<media_id>', methods=['POST'])
|
|
||||||
def synapse_unprotect_media(media_id):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/media/<server_name>/<media_id>', methods=['DELETE'])
|
|
||||||
def synapse_delete_single_media(media_id):
|
|
||||||
return jsonify({"deleted_media": ["cat"], "total": the_funny_number})
|
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/media/delete', methods=['POST'])
|
|
||||||
def synapse_delete_media():
|
|
||||||
return jsonify({"deleted_media": ["cat"], "total": the_funny_number})
|
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/media/<server_name>/delete', methods=['POST'])
|
@custom.route('/_synapse/admin/v1/media/<server_name>/delete', methods=['POST'])
|
||||||
def synapse_delete_media_from_server(server_name):
|
@custom.route('/_synapse/admin/v1/media/<server_name>/<media_id>', methods=['DELETE'])
|
||||||
|
@custom.route('/_synapse/admin/v1/media/delete', methods=['POST'])
|
||||||
|
async def synapse_delete_media_from_server(**kwargs):
|
||||||
return jsonify({"deleted_media": ["cat"], "total": the_funny_number})
|
return jsonify({"deleted_media": ["cat"], "total": the_funny_number})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/purge_media_cache', methods=['POST'])
|
@custom.route('/_synapse/admin/v1/purge_media_cache', methods=['POST'])
|
||||||
def synapse_delete_remote_media():
|
async def synapse_delete_remote_media():
|
||||||
return jsonify({"deleted": the_funny_number})
|
return jsonify({"deleted": the_funny_number})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/statistics/users/media')
|
@custom.route('/_synapse/admin/v1/statistics/users/media')
|
||||||
def synapse_media_stats():
|
async def synapse_media_stats():
|
||||||
return jsonify({"users":[{"displayname":"Vona","media_count":the_funny_number,"media_length":the_funny_number,"user_id":f"@vona:{server_name}"}],"total":the_funny_number})
|
return jsonify({"users":[{"displayname":"Vona","media_count":the_funny_number,"media_length":the_funny_number,"user_id":f"@vona:{server_name}"}],"total":the_funny_number})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/statistics/database/rooms')
|
@custom.route('/_synapse/admin/v1/statistics/database/rooms')
|
||||||
def synapse_room_stats():
|
async def synapse_room_stats():
|
||||||
return jsonify({"rooms": [{"room_id":room_dir_room['chunk'][0]['room_id'],"estimated_size":the_funny_number}]})
|
return jsonify({
|
||||||
|
"rooms": [{
|
||||||
@custom.route('/_synapse/admin/v1/background_updates/status')
|
"room_id": room_dir_room['chunk'][0]['room_id'],
|
||||||
def synapse_background_upate_status():
|
"estimated_size": the_funny_number * 420
|
||||||
return jsonify({"enabled":False})
|
}]
|
||||||
|
})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/background_updates/enabled', methods=['POST', 'GET'])
|
@custom.route('/_synapse/admin/v1/background_updates/enabled', methods=['POST', 'GET'])
|
||||||
def synapse_change_bg_update():
|
@custom.route('/_synapse/admin/v1/background_updates/status')
|
||||||
|
async def synapse_change_bg_update():
|
||||||
return jsonify({"enabled":False})
|
return jsonify({"enabled":False})
|
||||||
|
|
||||||
# No documentation on what Synapse actually returns for this API, so a blank dict for now.
|
# No documentation on what Synapse actually returns for this API, so a blank dict for now.
|
||||||
@custom.route('/_synapse/admin/v1/background_updates/start_job', methods=['POST'])
|
@custom.route('/_synapse/admin/v1/background_updates/start_job', methods=['POST'])
|
||||||
def synapse_bg_update_start_job():
|
async def synapse_bg_update_start_job():
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/event_reports')
|
@custom.route('/_synapse/admin/v1/event_reports')
|
||||||
def synapse_event_reports():
|
async def synapse_event_reports():
|
||||||
return jsonify({"event_reports": [{"event_id": make_event_id(),"id": the_funny_number,"reason": "vona","score": the_funny_number,"received_ts": the_funny_number,"room_id": room_dir_room['chunk'][0]['room_id'],"name": room_dir_room['chunk'][0]['name'],"sender": f"@vona:{server_name}","user_id": f"@vona:{server_name}"}],"total": the_funny_number})
|
return jsonify({
|
||||||
|
"event_reports": [{
|
||||||
|
"event_id": make_event_id(),
|
||||||
|
"id": the_funny_number,
|
||||||
|
"reason": "",
|
||||||
|
"score": the_funny_number,
|
||||||
|
"received_ts": the_funny_number,
|
||||||
|
"room_id": room_dir_room['chunk'][0]['room_id'],
|
||||||
|
"name": room_dir_room['chunk'][0]['name'],
|
||||||
|
"sender": f"@vona:{server_name}",
|
||||||
|
"user_id": f"@vona:{server_name}"
|
||||||
|
}],
|
||||||
|
"total": the_funny_number
|
||||||
|
})
|
||||||
|
|
||||||
@custom.route('/_synapse/admin/v1/event_reports/<report_id>', methods=['GET', 'DELETE'])
|
@custom.route('/_synapse/admin/v1/event_reports/<report_id>', methods=['GET', 'DELETE'])
|
||||||
def synapse_interact_with_reported_event(report_id):
|
async def synapse_interact_with_reported_event(report_id):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return jsonify({"event_id": make_event_id(),"event_json": {"auth_events": [],"content": {"msgtype": "m.text","body": "Number 15: Burger King Foot Lettuce.\nThe last thing you'd want in your Burger King burger is someones foot fungus, but as it turns out, that might be what you get. A 4channer uploaded a photo, anonymously to the site showcasing his feet in a plastic bin of lettuce with the statement \"This is the lettuce you eat at Burger King.\". Admittedly, he had shoes on, but thats even worse. The post went live at 11:38 PM on July 16 and a mere 20 minutes later the Burger King in question was alerted to the rogue employee. At least, I hope hes rogue. How did it happen? Well, the BK employee hadn't removed the EXIF data from the uploaded photo, which suggested that the culprit was somewhere in Mayfield Heights, Ohio. This was at 11:47. 3 minutes later, at 11:50, the Burger King branch was posted with wishes of happy unemployment. 5 minutes later, the news station was contacted by another 4channer, and 3 minutes later at 11:58 a link was posted: BK's tell us about us online forum. The foot photo, otherwise known as Exhibit A, was attached. Cleveland Seen Magazine contacted the BK in question and the next day when questioned, the breakfast shift manager said \"Oh, I know who that is, hes getting fired\". Mystery solved, by 4chan. Now we can go back to eating our fast food in peace.","format": "org.matrix.custom.html","formatted_body": "Number 15: Burger King Foot Lettuce.<br />The last thing you'd want in your Burger King burger is someones foot fungus, but as it turns out, that might be what you get. A 4channer uploaded a photo, anonymously to the site showcasing his feet in a plastic bin of lettuce with the statement "This is the lettuce you eat at Burger King.". Admittedly, he had shoes on, but thats even worse. The post went live at 11:38 PM on July 16 and a mere 20 minutes later the Burger King in question was alerted to the rogue employee. At least, I hope hes rogue. How did it happen? Well, the BK employee hadn't removed the EXIF data from the uploaded photo, which suggested that the culprit was somewhere in Mayfield Heights, Ohio. This was at 11:47. 3 minutes later, at 11:50, the Burger King branch was posted with wishes of happy unemployment. 5 minutes later, the news station was contacted by another 4channer, and 3 minutes later at 11:58 a link was posted: BK's tell us about us online forum. The foot photo, otherwise known as Exhibit A, was attached. Cleveland Seen Magazine contacted the BK in question and the next day when questioned, the breakfast shift manager said "Oh, I know who that is, hes getting fired". Mystery solved, by 4chan. Now we can go back to eating our fast food in peace."},"depth": the_funny_number,"hashes": {"sha256": "todo: replace with something proper"},"origin": server_name,"origin_server_ts": the_funny_number,"prev_events": [make_event_id()],"prev_state": [],"room_id": room_dir_room['chunk'][0]['room_id'],"sender": f"@vona:{server_name}","signatures": {server_name: {"ed25519:a_JaEG": base64.b64encode(os.urandom(32)).decode('utf-8')[:87]}}},"type": "m.room.message","unsigned": {"age_ts": the_funny_number},"id": the_funny_number,"reason": "vona","score": the_funny_number,"received_ts": the_funny_number,"room_id": room_dir_room['chunk'][0]['room_id'],"name": room_dir_room['chunk'][0]['name'],"sender": f"@vona:{server_name}","user_id": f"@vona:{server_name}"})
|
return jsonify({"event_id": make_event_id(),"event_json": {"auth_events": [],"content": {"msgtype": "m.text","body": "Number 15: Burger King Foot Lettuce.\nThe last thing you'd want in your Burger King burger is someones foot fungus, but as it turns out, that might be what you get. A 4channer uploaded a photo, anonymously to the site showcasing his feet in a plastic bin of lettuce with the statement \"This is the lettuce you eat at Burger King.\". Admittedly, he had shoes on, but thats even worse. The post went live at 11:38 PM on July 16 and a mere 20 minutes later the Burger King in question was alerted to the rogue employee. At least, I hope hes rogue. How did it happen? Well, the BK employee hadn't removed the EXIF data from the uploaded photo, which suggested that the culprit was somewhere in Mayfield Heights, Ohio. This was at 11:47. 3 minutes later, at 11:50, the Burger King branch was posted with wishes of happy unemployment. 5 minutes later, the news station was contacted by another 4channer, and 3 minutes later at 11:58 a link was posted: BK's tell us about us online forum. The foot photo, otherwise known as Exhibit A, was attached. Cleveland Seen Magazine contacted the BK in question and the next day when questioned, the breakfast shift manager said \"Oh, I know who that is, hes getting fired\". Mystery solved, by 4chan. Now we can go back to eating our fast food in peace.","format": "org.matrix.custom.html","formatted_body": "Number 15: Burger King Foot Lettuce.<br />The last thing you'd want in your Burger King burger is someones foot fungus, but as it turns out, that might be what you get. A 4channer uploaded a photo, anonymously to the site showcasing his feet in a plastic bin of lettuce with the statement "This is the lettuce you eat at Burger King.". Admittedly, he had shoes on, but thats even worse. The post went live at 11:38 PM on July 16 and a mere 20 minutes later the Burger King in question was alerted to the rogue employee. At least, I hope hes rogue. How did it happen? Well, the BK employee hadn't removed the EXIF data from the uploaded photo, which suggested that the culprit was somewhere in Mayfield Heights, Ohio. This was at 11:47. 3 minutes later, at 11:50, the Burger King branch was posted with wishes of happy unemployment. 5 minutes later, the news station was contacted by another 4channer, and 3 minutes later at 11:58 a link was posted: BK's tell us about us online forum. The foot photo, otherwise known as Exhibit A, was attached. Cleveland Seen Magazine contacted the BK in question and the next day when questioned, the breakfast shift manager said "Oh, I know who that is, hes getting fired". Mystery solved, by 4chan. Now we can go back to eating our fast food in peace."},"depth": the_funny_number,"hashes": {"sha256": "todo: replace with something proper"},"origin": server_name,"origin_server_ts": the_funny_number,"prev_events": [make_event_id()],"prev_state": [],"room_id": room_dir_room['chunk'][0]['room_id'],"sender": f"@vona:{server_name}","signatures": {server_name: {"ed25519:a_JaEG": base64.b64encode(os.urandom(32)).decode('utf-8')[:87]}}},"type": "m.room.message","unsigned": {"age_ts": the_funny_number},"id": the_funny_number,"reason": "vona","score": the_funny_number,"received_ts": the_funny_number,"room_id": room_dir_room['chunk'][0]['room_id'],"name": room_dir_room['chunk'][0]['name'],"sender": f"@vona:{server_name}","user_id": f"@vona:{server_name}"})
|
||||||
else:
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v1/federation/destinations")
|
||||||
|
async def synapse_federation_destinations():
|
||||||
|
return jsonify({
|
||||||
|
"destinations": [{}],
|
||||||
|
"total": 0
|
||||||
|
})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v1/federation/destinations/<destination>")
|
||||||
|
async def synapse_destination(destination):
|
||||||
|
return jsonify({
|
||||||
|
"destination": destination,
|
||||||
|
"retry_last_ts": the_funny_number,
|
||||||
|
"retry_interval": the_funny_number,
|
||||||
|
"failure_ts": the_funny_number,
|
||||||
|
"last_successful_stream_ordering": None
|
||||||
|
})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v1/federation/destinations/<destination>/rooms")
|
||||||
|
async def synapse_destination_rooms(destination):
|
||||||
|
return jsonify({
|
||||||
|
"rooms": [],
|
||||||
|
"total": 0
|
||||||
|
})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v1/registration_tokens")
|
||||||
|
async def synapse_reg_tokens():
|
||||||
|
return jsonify({
|
||||||
|
"registration_tokens": [{
|
||||||
|
"token": "Vona",
|
||||||
|
"uses_allowed": the_funny_number,
|
||||||
|
"pending": 0,
|
||||||
|
"completed": 1,
|
||||||
|
"expiry_time": None
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v1/registration_tokens/<token>", methods=["GET", "PUT", "DELETE"])
|
||||||
|
async def synapse_reg_token(token):
|
||||||
|
if request.method == "DELETE":
|
||||||
|
return jsonify({})
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"token": "Vona",
|
||||||
|
"uses_allowed": the_funny_number,
|
||||||
|
"pending": 0,
|
||||||
|
"completed": 1,
|
||||||
|
"expiry_time": None
|
||||||
|
})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v1/registration_tokens/new", methods=["POST"])
|
||||||
|
async def synapse_new_reg_token():
|
||||||
|
return jsonify({
|
||||||
|
"token": "Vona",
|
||||||
|
"uses_allowed": the_funny_number,
|
||||||
|
"pending": 0,
|
||||||
|
"completed": 1,
|
||||||
|
"expiry_time": None
|
||||||
|
})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v1/rooms")
|
||||||
|
async def synapse_rooms():
|
||||||
|
return jsonify({
|
||||||
|
"rooms": [],
|
||||||
|
"offset": 0,
|
||||||
|
"total_rooms": 0
|
||||||
|
})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v1/rooms/<room_id>/members")
|
||||||
|
async def synapse_room_members(room):
|
||||||
|
return jsonify({
|
||||||
|
"members": [
|
||||||
|
f"@vona:{server_name}"
|
||||||
|
],
|
||||||
|
"total": 1
|
||||||
|
})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v1/rooms/<room_id>/state")
|
||||||
|
async def synapse_room_state(room):
|
||||||
|
return jsonify({"state": []})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v1/rooms/<room_id>/state")
|
||||||
|
async def synapse_room_messages(room):
|
||||||
|
return jsonify({
|
||||||
|
"chunk": [],
|
||||||
|
"end": "vona",
|
||||||
|
"start": "vona"
|
||||||
|
})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v1/rooms/<room_id>/block", methods=["GET", "PUT"])
|
||||||
|
async def synapse_block_room(room):
|
||||||
|
return jsonify({"block": False})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v1/rooms/<room_id>", methods=["DELETE"])
|
||||||
|
async def synapse_room_delete(room):
|
||||||
|
return jsonify({
|
||||||
|
"kicked_users": [
|
||||||
|
f"@vona:{server_name}"
|
||||||
|
],
|
||||||
|
"failed_to_kick_users": [],
|
||||||
|
"local_aliases": [],
|
||||||
|
"new_room_id": f"!vona:{server_name}"
|
||||||
|
})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v2/rooms/<room_id>", methods=["DELETE"])
|
||||||
|
async def synapse_room_delete_v2(room):
|
||||||
|
return jsonify({"delete_id": "vona"})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v2/rooms/<room_id>/delete_status")
|
||||||
|
async def synapse_room_delete_status(room):
|
||||||
|
return jsonify({"results": []})
|
||||||
|
|
||||||
|
@custom.route("/_synapse/admin/v1/rooms/<room_id_or_alias>/forward_extremities", methods=["GET"])
|
||||||
|
async def synapse_forward_extremities(room):
|
||||||
|
if request.method == "DELETE":
|
||||||
|
return jsonify({"deleted": 0})
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"count": 1,
|
||||||
|
"results": [{
|
||||||
|
"event_id": make_event_id(),
|
||||||
|
"state_group": the_funny_number,
|
||||||
|
"depth": the_funny_number,
|
||||||
|
"received_ts": the_funny_number
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
|
||||||
# Dendrite - https://element-hq.github.io/dendrite/administration/adminapi
|
# Dendrite - https://element-hq.github.io/dendrite/administration/adminapi
|
||||||
@custom.route('/_dendrite/admin/evacuateUser/<userId>', methods=['POST'])
|
@custom.route('/_dendrite/admin/evacuateUser/<userId>', methods=['POST'])
|
||||||
def dendrite_evacuate_user(userId):
|
async def dendrite_evacuate_user(userId):
|
||||||
return jsonify({"affected": [room_dir_room['chunk'][0]['room_id']]})
|
return jsonify({"affected": [room_dir_room['chunk'][0]['room_id']]})
|
||||||
|
|
||||||
@custom.route('/_dendrite/admin/evacuateRoom/<roomId>', methods=['POST'])
|
@custom.route('/_dendrite/admin/evacuateRoom/<roomId>', methods=['POST'])
|
||||||
def dendrite_evacuate_room(roomId):
|
async def dendrite_evacuate_room(roomId):
|
||||||
return jsonify({"affected": [f"@vona:{server_name}"]})
|
return jsonify({"affected": [f"@vona:{server_name}"]})
|
||||||
|
|
||||||
@custom.route('/_dendrite/admin/resetPassword/<userId>', methods=['POST'])
|
@custom.route('/_dendrite/admin/resetPassword/<userId>', methods=['POST'])
|
||||||
def dendrite_reset_pswd(userId):
|
async def dendrite_reset_pswd(userId):
|
||||||
return jsonify({"password_updated":true})
|
return jsonify({"password_updated": True})
|
||||||
|
|
||||||
@custom.route('/_dendrite/admin/purgeRoom/<roomId>', methods=['POST'])
|
# Conduwuit/Tuwunel/Continuwuity
|
||||||
def dendrite_purge_room(roomId):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@custom.route('/_dendrite/admin/refreshDevices/<userId>', methods=['POST'])
|
|
||||||
def dendrite_refresh_devices(userId):
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
@custom.route('/_dendrite/admin/fulltext/reindex')
|
|
||||||
def dendrite_reindex():
|
|
||||||
return jsonify({})
|
|
||||||
|
|
||||||
# Conduwuit
|
|
||||||
@custom.route('/_conduwuit/local_user_count')
|
|
||||||
def conduwuit_user_count():
|
|
||||||
return jsonify({"count": 1})
|
|
||||||
|
|
||||||
@custom.route('/_conduwuit/server_version')
|
|
||||||
def conduwuit_server_version():
|
|
||||||
return jsonify({"name":"Vona","version":vona_version})
|
|
||||||
|
|
||||||
# Continuwuity
|
|
||||||
@custom.route('/_continuwuity/local_user_count')
|
@custom.route('/_continuwuity/local_user_count')
|
||||||
def continuwuity_user_count():
|
@custom.route('/_conduwuit/local_user_count')
|
||||||
|
@custom.route('/_tuwunel/local_user_count')
|
||||||
|
async def conduwuit_user_count():
|
||||||
return jsonify({"count": 1})
|
return jsonify({"count": 1})
|
||||||
|
|
||||||
@custom.route('/_continuwuity/server_version')
|
@custom.route('/_continuwuity/server_version')
|
||||||
def continuwuity_server_version():
|
@custom.route('/_conduwuit/server_version')
|
||||||
return jsonify({"name":"Vona","version":vona_version})
|
|
||||||
|
|
||||||
# Tuwunel
|
|
||||||
@custom.route('/_tuwunel/local_user_count')
|
|
||||||
def tuwunel_user_count():
|
|
||||||
return jsonify({"count": 1})
|
|
||||||
|
|
||||||
@custom.route('/_tuwunel/server_version')
|
@custom.route('/_tuwunel/server_version')
|
||||||
def tuwunel_server_version():
|
async def conduwuit_server_version():
|
||||||
return jsonify({"name":"Vona","version":vona_version})
|
return jsonify({"name":"Vona","version":vona_version})
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import nacl.signing
|
|||||||
import hashlib
|
import hashlib
|
||||||
import base64
|
import base64
|
||||||
import config
|
import config
|
||||||
|
import random
|
||||||
import copy
|
import copy
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import os
|
|
||||||
|
|
||||||
vona_version = "1.3.0"
|
vona_version = "1.4.0"
|
||||||
|
|
||||||
|
|
||||||
def canonical_json(value):
|
def canonical_json(value):
|
||||||
@@ -81,15 +81,17 @@ def sign_json_without_discard(data):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def make_event_id():
|
def make_event_id(seed=None):
|
||||||
event_id = "$"
|
if seed is not None:
|
||||||
|
random.seed(seed)
|
||||||
|
|
||||||
|
random_bytes = bytearray(random.getrandbits(8) for _ in range(32))
|
||||||
|
|
||||||
|
event_id = "$"
|
||||||
event_id += re.sub(
|
event_id += re.sub(
|
||||||
r"[\/+=]",
|
r"[\/+=]",
|
||||||
"_",
|
"_",
|
||||||
base64.b64encode(
|
base64.b64encode(random_bytes).decode("utf-8"),
|
||||||
os.urandom(32),
|
|
||||||
).decode("utf-8"),
|
|
||||||
).rstrip("=")[:44]
|
).rstrip("=")[:44]
|
||||||
|
|
||||||
event_id += ":" + config.server_name
|
event_id += ":" + config.server_name
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from flask import Blueprint, jsonify, request
|
|||||||
from config import server_name, the_funny_number
|
from config import server_name, the_funny_number
|
||||||
import time
|
import time
|
||||||
|
|
||||||
identity = Blueprint("matrix_identity", __name__)
|
identity = Blueprint("identity", __name__)
|
||||||
|
|
||||||
# This implements being an identity server.
|
# This implements being an identity server.
|
||||||
# I'm pretty sure only Element uses this,
|
# I'm pretty sure only Element uses this,
|
||||||
@@ -12,7 +12,19 @@ identity = Blueprint("matrix_identity", __name__)
|
|||||||
@identity.route("/_matrix/identity/versions")
|
@identity.route("/_matrix/identity/versions")
|
||||||
async def versions():
|
async def versions():
|
||||||
# Stolen from the vector.im identity server
|
# Stolen from the vector.im identity server
|
||||||
return jsonify({"versions":["r0.1.0","r0.2.0","r0.2.1","r0.3.0","v1.1","v1.2","v1.3","v1.4","v1.5"]})
|
return jsonify({
|
||||||
|
"versions": [
|
||||||
|
"r0.1.0",
|
||||||
|
"r0.2.0",
|
||||||
|
"r0.2.1",
|
||||||
|
"r0.3.0",
|
||||||
|
"v1.1",
|
||||||
|
"v1.2",
|
||||||
|
"v1.3",
|
||||||
|
"v1.4",
|
||||||
|
"v1.5"
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/identity-service-api/#authentication
|
# https://spec.matrix.org/v1.16/identity-service-api/#authentication
|
||||||
@@ -20,10 +32,12 @@ async def versions():
|
|||||||
async def account_info():
|
async def account_info():
|
||||||
return jsonify({"user_id": f"@vona:{server_name}"})
|
return jsonify({"user_id": f"@vona:{server_name}"})
|
||||||
|
|
||||||
|
|
||||||
@identity.route("/_matrix/identity/v2/account/logout", methods=['POST'])
|
@identity.route("/_matrix/identity/v2/account/logout", methods=['POST'])
|
||||||
async def logout():
|
async def logout():
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
|
||||||
@identity.route("/_matrix/identity/v2/account/register", methods=['POST'])
|
@identity.route("/_matrix/identity/v2/account/register", methods=['POST'])
|
||||||
async def register():
|
async def register():
|
||||||
return jsonify({"token":"vona"})
|
return jsonify({"token":"vona"})
|
||||||
@@ -37,28 +51,22 @@ async def policies():
|
|||||||
|
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/identity-service-api/#status-check
|
|
||||||
@identity.route('/_matrix/identity/v2')
|
@identity.route('/_matrix/identity/v2')
|
||||||
async def status():
|
async def status():
|
||||||
return jsonify({})
|
return jsonify({})
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/identity-service-api/#key-management
|
|
||||||
@identity.route('/_matrix/identity/v2/pubkey/ephemeral/isvalid')
|
@identity.route('/_matrix/identity/v2/pubkey/ephemeral/isvalid')
|
||||||
async def pubkey_eph_validity():
|
|
||||||
return jsonify({"valid":True})
|
|
||||||
|
|
||||||
@identity.route('/_matrix/identity/v2/pubkey/isvalid')
|
@identity.route('/_matrix/identity/v2/pubkey/isvalid')
|
||||||
async def pubkey_validity():
|
async def pubkey_validity():
|
||||||
return jsonify({"valid": True})
|
return jsonify({"valid": True})
|
||||||
|
|
||||||
@identity.route('/_matrix/identity/v2/pubkey/<key>')
|
@identity.route('/_matrix/identity/v2/pubkey/<key>')
|
||||||
async def get_key(key):
|
async def get_key(key):
|
||||||
return jsonify({"errcode":"M_NOT_FOUND","error":"The public key was not found"}), 404
|
return jsonify({
|
||||||
|
"errcode": "M_NOT_FOUND",
|
||||||
|
"error": "The public key was not found"
|
||||||
|
}), 404
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/identity-service-api/#association-lookup
|
|
||||||
@identity.route('/_matrix/identity/v2/hash_details')
|
@identity.route('/_matrix/identity/v2/hash_details')
|
||||||
async def hash_details():
|
async def hash_details():
|
||||||
return jsonify({"algorithms":["none","sha256"],"lookup_pepper": "vona"})
|
return jsonify({"algorithms":["none","sha256"],"lookup_pepper": "vona"})
|
||||||
@@ -72,22 +80,14 @@ async def lookup():
|
|||||||
else:
|
else:
|
||||||
return jsonify({"errcode": "M_INVALID_PEPPER","error": "Invalid pepper"})
|
return jsonify({"errcode": "M_INVALID_PEPPER","error": "Invalid pepper"})
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/identity-service-api/#establishing-associations
|
|
||||||
@identity.route('/_matrix/identity/v2/validate/email/requestToken', methods=['POST'])
|
@identity.route('/_matrix/identity/v2/validate/email/requestToken', methods=['POST'])
|
||||||
async def request_email_token():
|
@identity.route('/_matrix/identity/v2/validate/msisdn/requestToken', methods=['POST'])
|
||||||
|
async def request_validation_token():
|
||||||
return jsonify({"sid": str(the_funny_number)})
|
return jsonify({"sid": str(the_funny_number)})
|
||||||
|
|
||||||
@identity.route('/_matrix/identity/v2/validate/email/submitToken', methods=['GET', 'POST'])
|
@identity.route('/_matrix/identity/v2/validate/email/submitToken', methods=['GET', 'POST'])
|
||||||
async def submit_email_token():
|
|
||||||
return jsonify({"success":True})
|
|
||||||
|
|
||||||
@identity.route('/_matrix/identity/v2/validate/msisdn/requestToken', methods=['POST'])
|
|
||||||
async def request_phone_token():
|
|
||||||
return jsonify({"sid":str(the_funny_number)})
|
|
||||||
|
|
||||||
@identity.route('/_matrix/identity/v2/validate/msisdn/submitToken', methods=['GET', 'POST'])
|
@identity.route('/_matrix/identity/v2/validate/msisdn/submitToken', methods=['GET', 'POST'])
|
||||||
async def submit_phone_token():
|
async def submit_validation_token():
|
||||||
return jsonify({"success": True})
|
return jsonify({"success": True})
|
||||||
|
|
||||||
@identity.route('/_matrix/identity/v2/3pid/bind', methods=['POST'])
|
@identity.route('/_matrix/identity/v2/3pid/bind', methods=['POST'])
|
||||||
@@ -113,30 +113,41 @@ async def threepid_unbind():
|
|||||||
@identity.route('/_matrix/identity/v2/3pid/getValidated3pid')
|
@identity.route('/_matrix/identity/v2/3pid/getValidated3pid')
|
||||||
async def threepid_validated():
|
async def threepid_validated():
|
||||||
# Please email abuse@matrix.org
|
# Please email abuse@matrix.org
|
||||||
|
return jsonify({
|
||||||
return jsonify({"address":"abuse@matrix.org","medium":"email","validated_at":the_funny_number})
|
"address": "abuse@matrix.org",
|
||||||
|
"medium": "email",
|
||||||
|
"validated_at": the_funny_number
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/identity-service-api/#invitation-storage
|
# https://spec.matrix.org/v1.16/identity-service-api/#invitation-storage
|
||||||
@identity.route('/_matrix/identity/v2/store-invite', methods=['POST'])
|
@identity.route('/_matrix/identity/v2/store-invite', methods=['POST'])
|
||||||
async def invite():
|
async def invite():
|
||||||
return jsonify({"display_name":"Vona","public_keys":[{"key_validity_url":"https://example.com/_matrix/identity/v2/pubkey/isvalid","public_key":"ohyeah"},{"key_validity_url":"https://example.com/_matrix/identity/v2/pubkey/ephemeral/isvalid","public_key":"thisssssss"}],"token":"vona"})
|
return jsonify({
|
||||||
|
"display_name": "Vona",
|
||||||
|
"public_keys": [
|
||||||
|
{
|
||||||
|
"key_validity_url": f"https://{server_name}/_matrix/identity/v2/pubkey/isvalid",
|
||||||
|
"public_key":"ohyeah"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key_validity_url": f"https://{server_name}/_matrix/identity/v2/pubkey/ephemeral/isvalid",
|
||||||
|
"public_key":"thisssssss"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"token": "vona"
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/identity-service-api/#ephemeral-invitation-signing
|
# https://spec.matrix.org/v1.16/identity-service-api/#ephemeral-invitation-signing
|
||||||
@identity.route('/_matrix/identity/v2/sign-ed25519', methods=['POST'])
|
@identity.route('/_matrix/identity/v2/sign-ed25519', methods=['POST'])
|
||||||
async def invite_signing():
|
async def invite_signing():
|
||||||
# We don't want to sign any proivided
|
|
||||||
# JSON, thus make sure the keys match
|
|
||||||
|
|
||||||
required_keys = {'mxid', 'private_key', 'token'}
|
required_keys = {'mxid', 'private_key', 'token'}
|
||||||
d = data.get_json()
|
d = data.get_json()
|
||||||
|
|
||||||
if set(d.keys()) == required_keys:
|
if set(d.keys()) == required_keys:
|
||||||
return jsonify(sign_json(d))
|
return jsonify(sign_json(d))
|
||||||
else:
|
else:
|
||||||
# User submitted invalid data, reject
|
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"errcode": "M_UNRECOGNIZED",
|
"errcode": "M_UNRECOGNIZED",
|
||||||
"error": "Didn't recognize token"
|
"error": "Didn't recognize token"
|
||||||
|
|||||||
19
src/main.py
19
src/main.py
@@ -23,12 +23,22 @@ app.register_blueprint(custom)
|
|||||||
app.register_blueprint(server)
|
app.register_blueprint(server)
|
||||||
app.register_blueprint(apps)
|
app.register_blueprint(apps)
|
||||||
|
|
||||||
|
@app.before_request
|
||||||
|
async def preflight():
|
||||||
|
if request.method == "OPTIONS":
|
||||||
|
return "", 204
|
||||||
|
|
||||||
@app.after_request
|
@app.after_request
|
||||||
async def handle_logging(response):
|
async def handle_logging(response):
|
||||||
|
if request.method == "OPTIONS":
|
||||||
|
# Discard logs for OPTIONS
|
||||||
|
return 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]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
origin = "client"
|
origin = "client"
|
||||||
else:
|
else:
|
||||||
@@ -36,9 +46,16 @@ async def handle_logging(response):
|
|||||||
except:
|
except:
|
||||||
origin = "unknown"
|
origin = "unknown"
|
||||||
|
|
||||||
print(f"[{origin}] [{request.remote_addr}] [{datetime.now().strftime('%d/%b/%Y:%H:%M:%S')}] {request.method} {request.path} {response.status_code}")
|
print(f"[{origin}] [{request.remote_addr}] [{datetime.now().strftime('%d/%b/%Y:%H:%M:%S')}] {request.method} {request.full_path} {response.status_code}")
|
||||||
|
|
||||||
|
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
|
||||||
|
response.headers["Access-Control-Allow-Origin"] = "*"
|
||||||
|
response.headers["Access-Control-Allow-Headers"] = "*"
|
||||||
|
response.headers["Access-Control-Allow-Methods"] = "GET, HEAD, POST, PUT, DELETE, OPTIONS"
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
# Landing page
|
# Landing page
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
async def root():
|
async def root():
|
||||||
|
|||||||
@@ -1,29 +1,28 @@
|
|||||||
from flask import jsonify, Blueprint, request
|
from flask import jsonify, Blueprint, request
|
||||||
|
|
||||||
policy = Blueprint("policy_server", __name__)
|
policy = Blueprint("policy", __name__)
|
||||||
|
|
||||||
matrix_org = [
|
matrix_org = [
|
||||||
"dendrite.matrix.org",
|
"dendrite.matrix.org",
|
||||||
|
"beta.matrix.org",
|
||||||
"matrix.org",
|
"matrix.org",
|
||||||
"element.io",
|
"element.io",
|
||||||
"t2l.io",
|
"t2bot.io",
|
||||||
"t2bot.io"
|
"t2l.io"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@policy.route("/_matrix/policy/unstable/org.matrix.msc4284/event/<eventId>/check", methods=["POST"])
|
||||||
@policy.route("/_matrix/policy/v1/event/<eventId>/check", methods=["POST"])
|
@policy.route("/_matrix/policy/v1/event/<eventId>/check", methods=["POST"])
|
||||||
def check_event(eventId):
|
async def check_event(eventId):
|
||||||
if request.get_json()["origin"] in matrix_org:
|
if request.get_json()["origin"] in matrix_org:
|
||||||
return jsonify({"recommendation": "spam"})
|
return jsonify({"recommendation": "spam"})
|
||||||
else:
|
|
||||||
return jsonify({"recommendation": "ok"})
|
return jsonify({"recommendation": "ok"})
|
||||||
|
|
||||||
@policy.route(
|
|
||||||
"/_matrix/policy/unstable/org.matrix.msc4284/event/<eventId>/check",
|
@policy.route("/_matrix/policy/unstable/org.matrix.msc4284/sign", methods=["POST"])
|
||||||
methods=["POST"],
|
@policy.route("/_matrix/policy/v1/sign", methods=["POST"])
|
||||||
)
|
async def sign_event():
|
||||||
def check_event_unstable(eventId):
|
# NOTE: trolled
|
||||||
if request.get_json()["origin"] in matrix_org:
|
return jsonify({})
|
||||||
return jsonify({"recommendation": "spam"})
|
|
||||||
else:
|
|
||||||
return jsonify({"recommendation": "ok"})
|
|
||||||
|
|||||||
154
src/s2s.py
154
src/s2s.py
@@ -6,22 +6,20 @@ import json
|
|||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
|
|
||||||
server = Blueprint('matrix_server', __name__)
|
server = Blueprint("server", __name__)
|
||||||
|
|
||||||
# NOTE: Synapse rejects this for
|
|
||||||
# whatever reason. Still looking
|
def send_join(request, roomId) -> dict:
|
||||||
# into this issue.
|
|
||||||
def send_join(request, roomId):
|
|
||||||
event_chain = []
|
event_chain = []
|
||||||
event_hashes = []
|
event_hashes = []
|
||||||
|
|
||||||
event_ids = [
|
event_ids = [
|
||||||
globals.make_event_id(),
|
globals.make_event_id(seed=f"1_{roomId}"),
|
||||||
globals.make_event_id(),
|
globals.make_event_id(seed=f"2_{roomId}"),
|
||||||
globals.make_event_id(),
|
globals.make_event_id(seed=f"3_{roomId}"),
|
||||||
globals.make_event_id(),
|
globals.make_event_id(seed=f"4_{roomId}"),
|
||||||
globals.make_event_id(),
|
globals.make_event_id(seed=f"5_{roomId}"),
|
||||||
globals.make_event_id(),
|
globals.make_event_id(seed=f"6_{roomId}"),
|
||||||
]
|
]
|
||||||
|
|
||||||
create_event = {
|
create_event = {
|
||||||
@@ -214,10 +212,6 @@ def send_join(request, roomId):
|
|||||||
event_chain.append(shistory)
|
event_chain.append(shistory)
|
||||||
|
|
||||||
remote_join = request.get_json()
|
remote_join = request.get_json()
|
||||||
remote_join["auth_events"] = sguest_access["auth_events"]
|
|
||||||
remote_join["prev_events"] = [[shistory["event_id"], shistory["hashes"]]]
|
|
||||||
remote_join["depth"] = 7
|
|
||||||
remote_join = globals.hash_and_sign_event(remote_join)
|
|
||||||
|
|
||||||
response = {
|
response = {
|
||||||
"auth_chain": event_chain,
|
"auth_chain": event_chain,
|
||||||
@@ -227,18 +221,20 @@ def send_join(request, roomId):
|
|||||||
"state": event_chain
|
"state": event_chain
|
||||||
}
|
}
|
||||||
|
|
||||||
# debug statement
|
|
||||||
print(json.dumps(response, indent='\t'))
|
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@server.route('/_matrix/federation/v1/version')
|
@server.route("/_matrix/federation/v1/version")
|
||||||
def version():
|
async def version():
|
||||||
return jsonify({"server": {"version": globals.vona_version,"name": "Vona"}})
|
return jsonify({
|
||||||
|
"server": {
|
||||||
|
"version": globals.vona_version,
|
||||||
|
"name": "Vona"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
@server.route('/_matrix/key/v2/server')
|
@server.route("/_matrix/key/v2/server")
|
||||||
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": server_name,
|
||||||
@@ -251,14 +247,14 @@ def keys():
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
@server.route('/_matrix/federation/v1/query/directory')
|
@server.route('/_matrix/federation/v1/query/directory')
|
||||||
def room_query():
|
async def room_query():
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"room_id": room_dir_room['chunk'][0]['room_id'],
|
"room_id": globals.make_event_id().replace("$", "!"),
|
||||||
"servers": [server_name]
|
"servers": [server_name]
|
||||||
})
|
})
|
||||||
|
|
||||||
@server.route('/_matrix/federation/v1/media/download/<media_id>')
|
@server.route('/_matrix/federation/v1/media/download/<media_id>')
|
||||||
def download_media(media_id):
|
async def download_media(media_id):
|
||||||
# Auth media requires this to be
|
# Auth media requires this to be
|
||||||
# multipart despite not even using
|
# multipart despite not even using
|
||||||
# it for anything. Minor annoyance.
|
# it for anything. Minor annoyance.
|
||||||
@@ -280,44 +276,85 @@ def download_media(media_id):
|
|||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@server.route('/_matrix/federation/v1/media/thumbnail/<media_id>')
|
@server.route("/_matrix/federation/v1/media/thumbnail/<media_id>")
|
||||||
def thumbnail_media(media_id):
|
async def thumbnail_media(media_id):
|
||||||
return jsonify({"errcode": "M_TOO_CUTE","error": "Cat is too cute to thumbnail"}), 403
|
return jsonify({
|
||||||
|
"errcode": "M_TOO_CUTE",
|
||||||
|
"error": "Cat is too cute to thumbnail"
|
||||||
|
}), 418
|
||||||
|
|
||||||
@server.route('/_matrix/federation/v1/send_join/<roomId>/<eventId>', methods=['PUT'])
|
@server.route("/_matrix/federation/v1/send_join/<roomId>/<eventId>", methods=["PUT"])
|
||||||
def send_join_v1(roomId, eventId):
|
async def send_join_v1(roomId, eventId):
|
||||||
return jsonify([200, send_join(request, roomId)])
|
return jsonify([200, send_join(request, roomId)])
|
||||||
|
|
||||||
@server.route('/_matrix/federation/v2/send_join/<roomId>/<eventId>', methods=['PUT'])
|
@server.route("/_matrix/federation/v2/send_join/<roomId>/<eventId>", methods=["PUT"])
|
||||||
def send_join_v2(roomId, eventId):
|
async def send_join_v2(roomId, eventId):
|
||||||
return jsonify(send_join(request, roomId))
|
return jsonify(send_join(request, roomId))
|
||||||
|
|
||||||
@server.route('/_matrix/federation/v1/make_join/<roomId>/<userId>')
|
@server.route("/_matrix/federation/v1/make_join/<roomId>/<userId>")
|
||||||
def make_join(roomId, userId):
|
async def make_join(roomId, userId):
|
||||||
|
if roomId.split(":")[1] != server_name:
|
||||||
return jsonify({
|
return jsonify({
|
||||||
"event": {
|
"errcode": "M_FORBIDDEN",
|
||||||
|
"error": "You are not invited to this room."
|
||||||
|
}), 403
|
||||||
|
|
||||||
|
class bullshit:
|
||||||
|
def get_json():
|
||||||
|
return {}
|
||||||
|
|
||||||
|
state = send_join(
|
||||||
|
request=bullshit,
|
||||||
|
roomId=roomId
|
||||||
|
)["state"]
|
||||||
|
|
||||||
|
join = {
|
||||||
"content": {
|
"content": {
|
||||||
"join_authorised_via_users_server": f"@vona:{server_name}",
|
"join_authorised_via_users_server": f"@vona:{server_name}",
|
||||||
"membership": "join"
|
"membership": "join"
|
||||||
},
|
},
|
||||||
"origin": server_name,
|
"origin": server_name,
|
||||||
"origin_server_ts": str(the_funny_number),
|
"origin_server_ts": 7,
|
||||||
"room_id": roomId,
|
"room_id": roomId,
|
||||||
"sender": userId,
|
"sender": userId,
|
||||||
"state_key": userId,
|
"state_key": userId,
|
||||||
"type": "m.room.member"
|
"type": "m.room.member",
|
||||||
},
|
"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"]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
join["prev_events"] = [[
|
||||||
|
state[5]["event_id"],
|
||||||
|
state[5]["hashes"]
|
||||||
|
]]
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"event": globals.hash_and_sign_event(join),
|
||||||
"room_version": "2"
|
"room_version": "2"
|
||||||
})
|
})
|
||||||
|
|
||||||
@server.route('/_matrix/federation/v1/publicRooms', methods=['POST', 'GET'])
|
@server.route('/_matrix/federation/v1/publicRooms', methods=['POST', 'GET'])
|
||||||
def room_directory():
|
async def room_directory():
|
||||||
return jsonify(room_dir_room)
|
return jsonify(room_dir_room)
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/server-server-api/#transactions
|
# https://spec.matrix.org/v1.16/server-server-api/#transactions
|
||||||
@server.route('/_matrix/federation/v1/send/<txnId>', methods=['PUT'])
|
@server.route('/_matrix/federation/v1/send/<txnId>', methods=["PUT"])
|
||||||
def receive_txn(txnId):
|
async def receive_txn(txnId):
|
||||||
# We will need to implement a way to store every
|
# We will need to implement a way to store every
|
||||||
# event we need if we want to send events in the
|
# event we need if we want to send events in the
|
||||||
# future. We don't send events currently, however.
|
# future. We don't send events currently, however.
|
||||||
@@ -344,7 +381,7 @@ def receive_txn(txnId):
|
|||||||
return jsonify(response)
|
return jsonify(response)
|
||||||
|
|
||||||
@server.route('/_matrix/federation/v1/query/profile')
|
@server.route('/_matrix/federation/v1/query/profile')
|
||||||
def user_profile():
|
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':
|
||||||
@@ -358,6 +395,7 @@ def user_profile():
|
|||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/server-server-api/#device-management
|
# https://spec.matrix.org/v1.16/server-server-api/#device-management
|
||||||
|
@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({
|
||||||
@@ -366,28 +404,30 @@ async def user_devices(user):
|
|||||||
"user_id": f"@vona:{server_name}"
|
"user_id": f"@vona:{server_name}"
|
||||||
})
|
})
|
||||||
|
|
||||||
@server.route(f'/_matrix/federation/v1/user/devices/@/:{server_name}')
|
|
||||||
async def user_devices_fuck_flask():
|
|
||||||
return jsonify({
|
|
||||||
"devices": [],
|
|
||||||
"stream_id": the_funny_number,
|
|
||||||
"user_id": f"@vona:{server_name}"
|
|
||||||
})
|
|
||||||
|
|
||||||
@server.route('/_matrix/federation/v1/user/keys/query', methods=['POST'])
|
@server.route('/_matrix/federation/v1/user/keys/query', methods=['POST'])
|
||||||
def user_keys():
|
async def user_keys():
|
||||||
return jsonify({"device_keys":{f"@vona:{server_name}":{}}})
|
try:
|
||||||
|
users = request.json["device_keys"]
|
||||||
|
except:
|
||||||
|
return jsonify({
|
||||||
|
"errcode": "M_NOT_FOUND",
|
||||||
|
"error": "User does not exist"
|
||||||
|
}), 404
|
||||||
|
|
||||||
|
return jsonify({"device_keys": users})
|
||||||
|
|
||||||
|
|
||||||
# https://spec.matrix.org/v1.16/server-server-api/#inviting-to-a-room
|
@server.route('/_matrix/federation/v2/invite/<room>/<txnId>', methods=["PUT"])
|
||||||
@server.route('/_matrix/federation/v2/invite/<room>/<txnId>', methods=['PUT'])
|
async def invite_user_v2(room, txnId):
|
||||||
def invite_user_v2(room, txnId):
|
|
||||||
return invite_user(request.data)
|
return invite_user(request.data)
|
||||||
|
|
||||||
@server.route('/_matrix/federation/v1/invite/<room>/<txnId>', methods=['PUT'])
|
|
||||||
def invite_user_v1(room, txnId):
|
@server.route('/_matrix/federation/v1/invite/<room>/<txnId>', methods=["PUT"])
|
||||||
|
async def invite_user_v1(room, txnId):
|
||||||
return [200, invite_user(request.data)]
|
return [200, invite_user(request.data)]
|
||||||
|
|
||||||
|
|
||||||
def invite_user(data):
|
def invite_user(data):
|
||||||
try:
|
try:
|
||||||
invite_data = json.loads(data)
|
invite_data = json.loads(data)
|
||||||
|
|||||||
Reference in New Issue
Block a user