Files
matrix-vona/src/c2s.py
2025-09-05 15:08:49 -04:00

411 lines
17 KiB
Python

from config import server_name, users_can_register, room_dir_room, cat, the_funny_number
from flask import Blueprint, jsonify, request, send_file
import asyncio
import random
import os
client = Blueprint('matrix_client', __name__)
@client.route('/_matrix/client/versions')
def client_version():
return jsonify({"versions":["r0.0.1","r0.1.0","r0.2.0","r0.3.0","r0.4.0","r0.5.0","r0.6.0","r0.6.1","v1.1","v1.2","v1.3","v1.4","v1.5","v1.6","v1.7","v1.8","v1.9","v1.10","v1.11"],"unstable_features":{"org.matrix.label_based_filtering":True,"org.matrix.e2e_cross_signing":True,"org.matrix.msc2432":True,"uk.half-shot.msc2666.query_mutual_rooms":True,"io.element.e2ee_forced.public":False,"io.element.e2ee_forced.private":False,"io.element.e2ee_forced.trusted_private":False,"org.matrix.msc3026.busy_presence":False,"org.matrix.msc2285.stable":True,"org.matrix.msc3827.stable":True,"org.matrix.msc3440.stable":True,"org.matrix.msc3771":True,"org.matrix.msc3773":False,"fi.mau.msc2815":True,"fi.mau.msc2659.stable":True,"org.matrix.msc3882":False,"org.matrix.msc3881":False,"org.matrix.msc3874":False,"org.matrix.msc3912":False,"org.matrix.msc3981":True,"org.matrix.msc3391":False,"org.matrix.msc4069":False,"org.matrix.msc4028":False,"org.matrix.msc4108":False,"org.matrix.msc4140":False,"org.matrix.simplified_msc3575":True,"uk.tcpip.msc4133":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"})
else:
return jsonify({"errcode":"M_INVALID_PARAM","error":"Expected UserID string to start with '@'"})
@client.route('/_matrix/client/v3/rooms/<roomId>/members')
def room_member_count(roomId):
return jsonify({"errcode":"M_MISSING_TOKEN","error":"M_MISSING_TOKEN: Missing access token."})
@client.route('/_matrix/client/v3/account/whoami')
def whoami():
return jsonify({
"device_id": "VVOONNAA",
"user_id": f"@vona:{server_name}"
})
@client.route('/_matrix/client/v3/register', methods=['POST'])
def register():
if users_can_register:
data = request.get_json()
if data and 'auth' in data:
return jsonify({
"user_id": f"@vona:{server_name}",
"home_server": f"{server_name}",
"access_token": "vona",
"device_id": "VVOONNAA"
})
else:
return jsonify({
"session": os.urandom(32).hex(),
"flows": [{"stages": ["m.login.dummy"]}],
"params": {}
}), 401
else:
return jsonify({"errcode": "M_FORBIDDEN", "error": "M_FORBIDDEN: Registration has been disabled."}), 403
@client.route('/_matrix/client/v3/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return jsonify({"flows":[{"type":"m.login.password"},{"type":"m.login.application_service"},{"type":"m.login.token","get_login_token":True}]})
elif request.method == 'POST':
return jsonify({"access_token": "vona","device_id": "VVOONNAA","user_id": f"@vona:{server_name}"})
@client.route('/_matrix/client/v3/account/password/email/requestToken', methods=['POST'])
def pswd_reset():
return jsonify({"errcode":"M_THREEPID_NOT_FOUND","error":"Email not found"}), 400
@client.route('/_matrix/client/v3/keys/upload', methods=['POST'])
def key_upload():
return jsonify({"one_time_key_counts":{"signed_curve25519":50}})
@client.route('/_matrix/client/v3/room_keys/version', methods=['POST', 'GET'])
def roomkeys():
if request.method == 'POST':
return jsonify({
"algorithm": "m.megolm_backup.v1.curve25519-aes-sha2",
"auth_data":
{
"public_key":"vona",
"signatures": {
f"@vona:{server_name}": {
"ed25519:deviceid": "vona"
}
}
},
"count": the_funny_number,
"etag": "vona",
"version":str(the_funny_number)
})
return jsonify({})
@client.route('/_matrix/client/v3/capabilities')
def capabilities():
return jsonify({"capabilities":{"m.room_versions":{"default":"1337","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":["na.vo.hafjagger"],"disallowed":["org.example.secret_field"]}}})
@client.route('/_matrix/client/v3/pushrules/')
def pushrules():
# 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/join/<room>', methods=['POST'])
def join_room(room):
# TODO: Actually implement this
return jsonify({"errcode":"M_FORBIDDEN","error":"You are not invited to this room."}), 403
@client.route('/_matrix/client/v3/rooms/<room>/invite', methods=['POST'])
def invite_room(room):
return jsonify({})
@client.route('/_matrix/client/v3/knock/<room>', methods=['POST'])
def knock_room(room):
return jsonify({"errcode":"M_FORBIDDEN","error":"You are not allowed to knock on this room."}), 403
@client.route('/_matrix/client/v3/rooms/<room>/join', methods=['POST'])
def join_roomId(room):
return jsonify({"errcode":"M_FORBIDDEN","error":"You are not invited to this room."}), 403
@client.route('/_matrix/client/v3/sync')
async def sync():
wait_time = 0
if 'timeout' in request.args:
if 'timeout' in request.args:
try:
wait_time = int(request.args.get('timeout')) / 1000
except:
pass
await asyncio.sleep(wait_time)
return jsonify({
"next_batch": f"{os.urandom(64).hex()}",
"presence": {},
"device_one_time_keys_count": {"signed_curve25519": 50},
"org.matrix.msc2732.device_unused_fallback_key_types": ["signed_curve25519"],
"device_unused_fallback_key_types": ["signed_curve25519"],
"rooms": {
"join": {
f"!{os.urandom(64).hex()}:{server_name}": {
"timeline": {
"events": [],
"prev_batch": f"{random.randint(32095,309390)}",
"limited": False
},
"state": {"events": []},
"account_data": {"events": []},
"ephemeral": {"events": []},
"unread_notifications": {
"notification_count": 0,
"highlight_count": 0
},
"summary": {}
}
}
}
})
@client.route('/_matrix/client/v3/rooms/<room>/send/<eventType>/<txnId>', methods=['POST', 'PUT'])
def send_message(room, eventType, txnId):
return jsonify({"event_id": f"${os.urandom(16).hex()}:{server_name}"}), 200
@client.route('/_matrix/client/v3/user_directory/search', methods=['POST'])
def user_directory():
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')
def devices():
return jsonify({"devices":[{"device_id":"VVOONNAA","display_name":"Vona","last_seen_ip":"127.0.0.1","last_seen_ts":the_funny_number}]})
@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})
elif request.method == 'DELETE':
return jsonify({})
elif request.method == 'PUT':
return jsonify({})
@client.route('/_matrix/client/v3/delete_devices', methods=['POST'])
def delete_devices():
return jsonify({})
@client.route('/_matrix/client/v3/logout', methods=['POST'])
def logout():
return jsonify({})
@client.route('/_matrix/client/v3/logout/all', methods=['POST'])
def logout_all():
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({"errcode": "M_LIMIT_EXCEEDED","error": "Too many requests","retry_after_ms": 99999999999999999999999999999999999999999999999999999999999999999999999999999999999}), 429
@client.route('/_matrix/client/unstable/im.nheko.summary/rooms/<roomId>/summary')
def nheko_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": str(the_funny_number),
}
)
@client.route('/_matrix/client/v1/room_summary/<roomId>')
def msc_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": str(the_funny_number),
}
)
@client.route('/_matrix/client/r0/directory/room/<roomId>')
def r0_room_query(roomId):
return jsonify(
{
"room_id": room_dir_room['chunk'][0]['room_id'],
"servers": [
"matrix.org",
"envs.net",
"4d2.org"
]
}
)
@client.route('/_matrix/client/r0/directory/list/room/<roomId>')
def r0_room_vis(roomId):
return jsonify({"visibility": "public"})
@client.route('/_matrix/client/r0/publicRooms')
def r0_room_directory():
return jsonify(room_dir_room)
@client.route('/_matrix/media/r0/thumbnail/<server>/<file>')
def r0_media_thumbnail(server, file):
return send_file(cat)
@client.route('/_matrix/media/v1/thumbnail/<server>/<file>')
def v1_media_thumbnail(server, file):
return send_file(cat)
@client.route('/_matrix/client/v1/media/thumbnail/<s>/<f>')
def media_thumbnail(s, f):
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/r0/register/available')
def r0_username_available():
return jsonify({"available": True})
@client.route('/_matrix/client/v3/register/available')
def v3_username_available():
return jsonify({"available": True})
@client.route('/_matrix/client/v3/thirdparty/protocols')
def thirdparty_protocols():
return jsonify({})
@client.route('/_matrix/media/v3/preview_url')
def url_preview():
return jsonify({
"matrix:image:size": 102400,
"og:description": "look at this cool cat",
"og:image": f"mxc://{server_name}/ascERGshawAWawugaAcauga",
"og:image:height": 48,
"og:image:type": "image/jpg",
"og:image:width": 48,
"og:title": "cool cat"
})
@client.route('/_matrix/client/v1/media/preview_url')
def media_preview():
response = send_file(cat)
response.headers['Content-Disposition'] = f'inline; filename="cat.jpg"'
response.headers['Content-Type'] = 'image/jpg'
return response
@client.route('/_matrix/media/v1/create', methods=['POST'])
def create_mxc():
return jsonify({"content_uri": f"mxc://vona.squarebowl.club/{os.urandom(10).hex()}"})
@client.route('/_matrix/media/v3/upload', methods=['POST'])
def upload_media():
return jsonify({"content_uri": f"mxc://vona.squarebowl.club/{os.urandom(10).hex()}"})
@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')
def media_config():
return jsonify({"m.upload.size": the_funny_number})
@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'])
def user_profile_keys(userId, key):
if request.method == 'PUT' or request.method == 'DELETE':
return jsonify({})
elif request.method == 'GET':
if key == 'avatar_url':
return jsonify({"avatar_url":f"mxc://{server_name}/cat"})
elif key == 'displayname':
return jsonify({"displayname":"Vona"})
else:
return jsonify({"errcode": "M_NOT_FOUND","error": "The requested profile key does not exist."})
@client.route('/_matrix/client/v3/profile/<userId>')
def user_profile(userId):
return jsonify({"avatar_url":f"mxc://{server_name}/cat","displayname":"Vona"})
@client.route('/_matrix/client/v3/rooms/<roomId>/messages')
def room_messages(roomId):
return jsonify({
"chunk": [
{
"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 &quot;This is the lettuce you eat at Burger King.&quot;. 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 &quot;Oh, I know who that is, hes getting fired&quot;. Mystery solved, by 4chan. Now we can go back to eating our fast food in peace."
},
"event_id": f"{os.urandom(16).hex()}:{server_name}",
"origin_server_ts": the_funny_number,
"room_id": roomId,
"sender": f"@vona:{server_name}",
"type": "m.room.message",
"unsigned": {}
},
{
"content": {
"name": "Vona"
},
"event_id": f"{os.urandom(16).hex()}:{server_name}",
"origin_server_ts": the_funny_number,
"room_id": roomId,
"sender": f"@vona:{server_name}",
"state_key": "",
"type": "m.room.name",
"unsigned": {}
}
],
"end": 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'])
async def query_keys():
# Should be replaced with
# something proper eventually.
return jsonify({})