This repository has been archived on 2024-07-30. You can view files and clone it, but cannot push or open issues or pull requests.
python-aternos/python_aternos/atwss.py

142 lines
3.3 KiB
Python
Raw Normal View History

2022-01-22 14:10:30 +03:00
import enum
import json
import asyncio
2022-04-06 10:44:14 +03:00
import logging
2022-01-22 14:10:30 +03:00
import websockets
from typing import Union, Any, Dict, Callable, Coroutine
2022-03-25 15:45:38 +03:00
from typing import TYPE_CHECKING
2022-01-22 14:10:30 +03:00
from .atconnect import REQUA
2022-03-25 15:45:38 +03:00
if TYPE_CHECKING:
from .atserver import AternosServer
2022-01-22 14:10:30 +03:00
2022-04-06 10:44:14 +03:00
class Streams(enum.Enum):
status = (0,None)
queue = (1,None)
console = (2,'console')
ram = (3,'heap')
tps = (4,'tick')
def __init__(self, num:int, stream:str):
self.num = num
self.stream = stream
2022-01-22 14:10:30 +03:00
class AternosWss:
2022-03-25 15:45:38 +03:00
def __init__(self, atserv:'AternosServer', autoconfirm:bool=False) -> None:
2022-01-22 14:10:30 +03:00
2022-03-25 15:45:38 +03:00
self.atserv = atserv
self.cookies = atserv.atconn.session.cookies
self.session = self.cookies['ATERNOS_SESSION']
2022-04-06 10:44:14 +03:00
self.servid = atserv.servid
2022-01-22 14:10:30 +03:00
self.recv = {}
2022-03-25 15:45:38 +03:00
self.autoconfirm = autoconfirm
self.confirmed = False
async def confirm(self) -> None:
self.atserv.confirm()
2022-01-22 14:10:30 +03:00
2022-04-06 10:44:14 +03:00
def wssreceiver(self, stream:Streams) -> Callable[[Callable[[Any],Coroutine[Any,Any,None]]],Any]:
2022-01-22 14:10:30 +03:00
def decorator(func:Callable[[Any],Coroutine[Any,Any,None]]) -> None:
self.recv[stream] = func
return decorator
async def connect(self) -> None:
headers = [
2022-03-25 15:45:38 +03:00
('Host', 'aternos.org'),
2022-01-22 14:10:30 +03:00
('User-Agent', REQUA),
(
'Cookie',
2022-03-25 15:45:38 +03:00
f'ATERNOS_SESSION={self.session}; ' + \
2022-01-22 14:10:30 +03:00
f'ATERNOS_SERVER={self.servid}'
)
]
self.socket = await websockets.connect(
2022-03-25 15:45:38 +03:00
'wss://aternos.org/hermes/',
origin='https://aternos.org',
2022-01-22 14:10:30 +03:00
extra_headers=headers
)
2022-04-06 10:44:14 +03:00
@self.wssreceiver(Streams.status)
async def confirmfunc(msg):
# Autoconfirm
if not self.autoconfirm:
return
if msg['class'] == 'queueing' \
and msg['queue']['pending'] == 'pending'\
and not self.confirmed:
self.confirm()
@self.wssreceiver(Streams.status)
async def streamsfunc(msg):
if msg['status'] == 2:
# Automatically start streams
for strm in self.recv:
if not isinstance(strm,Streams):
continue
if strm.stream:
logging.debug(f'Enabling {strm.stream} stream')
await self.send({
'stream': strm.stream,
'type': 'start'
})
2022-03-25 15:45:38 +03:00
await self.wssworker()
2022-01-22 14:10:30 +03:00
async def close(self) -> None:
await self.socket.close()
del self.socket
async def send(self, obj:Union[Dict[str, Any],str]) -> None:
if isinstance(obj, dict):
obj = json.dumps(obj)
2022-04-06 10:44:14 +03:00
await self.socket.send(obj)
2022-01-22 14:10:30 +03:00
async def wssworker(self) -> None:
2022-03-25 15:45:38 +03:00
keep = asyncio.create_task(self.keepalive())
msgs = asyncio.create_task(self.receiver())
2022-01-22 14:10:30 +03:00
await keep
await msgs
async def keepalive(self) -> None:
while True:
await asyncio.sleep(49)
await self.socket.send('{"type":"\u2764"}')
async def receiver(self) -> None:
while True:
data = await self.socket.recv()
obj = json.loads(data)
2022-04-06 10:44:14 +03:00
msgtype = -1
2022-01-22 14:10:30 +03:00
if obj['type'] == 'line':
msgtype = Streams.console
msg = obj['data'].strip('\r\n ')
elif obj['type'] == 'heap':
msgtype = Streams.ram
msg = int(obj['data']['usage'])
elif obj['type'] == 'tick':
msgtype = Streams.tps
ticks = 1000 / obj['data']['averageTickTime']
msg = 20 if ticks > 20 else ticks
elif obj['type'] == 'status':
msgtype = Streams.status
msg = json.loads(obj['message'])
if msgtype in self.recv:
asyncio.create_task(
2022-01-22 14:10:30 +03:00
self.recv[msgtype](msg)
)