115 lines
4.3 KiB
Python
115 lines
4.3 KiB
Python
"""
|
|
Copyright (C) 2024 Skylar Widulski <cobra@vern.cc>
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as
|
|
published by the Free Software Foundation, either version 3 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
"""
|
|
|
|
import nio
|
|
import asyncio
|
|
import aiofiles
|
|
from promise import Promise
|
|
import json
|
|
import os
|
|
import sys
|
|
from xrcon.client import XRcon
|
|
import subprocess
|
|
from config import (mx_room_id, mx_user_id, mx_homeserver, mx_pass,
|
|
xon_host, xon_port, xon_name, xon_pass)
|
|
|
|
source_url = 'http://git.vern.cc/cobra/xonotic-bridge'
|
|
|
|
def esc(string):
|
|
return string.replace('\n', ' ')
|
|
|
|
class XonoticBridge:
|
|
def __init__(self, *args, **kwargs):
|
|
self.xon = XRcon(xon_host, xon_port, xon_pass)
|
|
self.client = nio.AsyncClient(mx_homeserver, mx_user_id)
|
|
self.xon.connect()
|
|
if not os.path.exists("xonotic.json"):
|
|
response = self.client.login(mx_pass)
|
|
print(response)
|
|
if isinstance(response, nio.LoginResponse):
|
|
write_creds(response, mx_homeserver)
|
|
print("Logged in. Restart the program")
|
|
self.client.close()
|
|
return
|
|
else:
|
|
with open("xonotic.json", "r") as f:
|
|
contents = f.read()
|
|
config = json.loads(contents)
|
|
self.client = nio.AsyncClient(config["homeserver"])
|
|
self.client.access_token = config["access_token"]
|
|
self.client.user_id = config["user_id"]
|
|
self.client.device_id = config["device_id"]
|
|
|
|
async def watch_xon(self):
|
|
lastdata = ''
|
|
if not os.path.exists('logpipe'):
|
|
os.mkfifo('logpipe', 0o600)
|
|
async with aiofiles.open('logpipe') as fifo:
|
|
while (True):
|
|
if (self.client.logged_in):
|
|
try:
|
|
async for data in fifo:
|
|
print(data)
|
|
if data != '' and data != lastdata:
|
|
if not data.startswith(f"<{xon_name}> @"):
|
|
await self.client.room_send(mx_room_id, message_type="m.room.message", content={"msgtype": "m.text", "body": data})
|
|
lastdata = data
|
|
except Exception as e:
|
|
raise e
|
|
continue
|
|
await asyncio.sleep(0)
|
|
|
|
async def watch_matrix(self):
|
|
with open("next_batch","r") as next_batch_token:
|
|
self.client.next_batch = next_batch_token.read()
|
|
|
|
await self.client.room_send(mx_room_id, message_type="m.room.message", content={"msgtype": "m.text", "body": f"Starting Xonotic bridge. Source code: {source_url}"})
|
|
|
|
while (True):
|
|
sync_response = await self.client.sync(30000)
|
|
|
|
with open("next_batch","w+") as next_batch_token:
|
|
next_batch_token.write(sync_response.next_batch)
|
|
|
|
if len(sync_response.rooms.join) > 0:
|
|
joins = sync_response.rooms.join
|
|
for room_id in joins:
|
|
for event in joins[room_id].timeline.events:
|
|
if isinstance(event, nio.RoomMessageText) and event.sender != self.client.user_id:
|
|
print(f"{event.sender}: {event.body}")
|
|
self.xon.send(f'say "{event.sender}: {esc(event.body)}"')
|
|
|
|
def write_creds(resp: nio.LoginResponse, homeserver) -> None:
|
|
with open("xonotic.json", "w") as f:
|
|
json.dump(
|
|
{
|
|
"homeserver": homeserver,
|
|
"user_id": resp.user_id,
|
|
"device_id": resp.device_id,
|
|
"access_token": resp.access_token,
|
|
},
|
|
f,
|
|
)
|
|
|
|
async def main():
|
|
print("Starting...")
|
|
bridge = XonoticBridge()
|
|
await Promise.all([bridge.watch_xon(), bridge.watch_matrix()]);
|
|
|
|
asyncio.run(main())
|
|
|