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/atserver.py

463 lines
11 KiB
Python
Raw Normal View History

2022-07-01 13:28:39 +03:00
"""Aternos Minecraft server"""
import re
import json
import enum
from typing import Any, Dict, List
from functools import partial
2021-10-08 18:35:20 +03:00
from .atconnect import BASE_URL, AJAX_URL
2022-03-18 17:38:36 +03:00
from .atconnect import AternosConnect
2023-05-24 16:41:33 +03:00
from .atwss import AternosWss
2022-03-18 17:38:36 +03:00
from .atplayers import PlayersList
2022-06-16 14:40:10 +03:00
from .atplayers import Lists
2023-05-24 16:41:33 +03:00
from .atfm import FileManager
from .atconf import AternosConfig
from .aterrors import AternosError
2023-05-24 16:41:33 +03:00
from .aterrors import ServerStartError
2022-06-23 14:13:56 +03:00
SERVER_URL = f'{AJAX_URL}/server'
status_re = re.compile(
r'<script>\s*var lastStatus\s*?=\s*?(\{.+?\});?\s*<\/script>'
)
2022-03-18 17:38:36 +03:00
class Edition(enum.IntEnum):
2022-06-16 14:40:10 +03:00
"""Server edition type enum (java, bedrock)"""
2022-06-23 14:13:56 +03:00
java = 0
bedrock = 1
2022-06-16 14:40:10 +03:00
class Status(enum.IntEnum):
2022-06-16 14:40:10 +03:00
2022-06-23 14:13:56 +03:00
"""Server numeric status enum.
It is highly recommended to use
`AternosServer.status` instead of
`AternosServer.status_num`"""
off = 0
on = 1
2022-06-23 14:13:56 +03:00
starting = 2
shutdown = 3
loading = 6
2022-06-23 14:13:56 +03:00
error = 7
preparing = 10
2022-06-23 14:13:56 +03:00
confirm = 10
2022-06-16 14:40:10 +03:00
2021-10-08 18:35:20 +03:00
class AternosServer:
"""Class for controlling your Aternos Minecraft server"""
2022-06-23 14:13:56 +03:00
def __init__(
self, servid: str,
atconn: AternosConnect,
autofetch: bool = False) -> None:
"""Class for controlling your Aternos Minecraft server
Args:
servid (str): Unique server IDentifier
atconn (AternosConnect):
AternosConnect instance with initialized Aternos session
autofetch (bool, optional): Automatically call
`fetch()` to get all info
"""
2022-06-23 14:13:56 +03:00
self.servid = servid
self.atconn = atconn
self._info: Dict[str, Any] = {}
self.atserver_request = partial(
self.atconn.request_cloudflare,
reqcookies={
'ATERNOS_SERVER': self.servid,
}
)
if autofetch:
2022-06-23 14:13:56 +03:00
self.fetch()
def fetch(self) -> None:
"""Get all server info"""
2022-06-23 14:13:56 +03:00
page = self.atserver_request(
f'{BASE_URL}/server', 'GET'
2022-06-23 14:13:56 +03:00
)
match = status_re.search(page.text)
if match is None:
raise AternosError('Unable to parse lastStatus object')
self._info = json.loads(match[1])
2022-06-23 14:13:56 +03:00
def wss(self, autoconfirm: bool = False) -> AternosWss:
"""Returns AternosWss instance for
listening server streams in real-time
2022-06-23 14:13:56 +03:00
Args:
autoconfirm (bool, optional):
Automatically start server status listener
when AternosWss connects to API to confirm
server launching
Returns:
AternosWss object
2022-06-23 14:13:56 +03:00
"""
return AternosWss(self, autoconfirm)
2022-07-01 13:28:39 +03:00
def start(
self,
headstart: bool = False,
access_credits: bool = False,
2022-07-01 13:28:39 +03:00
accepteula: bool = True) -> None:
2022-06-23 14:13:56 +03:00
"""Starts a server
Args:
headstart (bool, optional): Start a server in
the headstart mode which allows
you to skip all queue
access_credits (bool, optional):
Some new parameter in Aternos API,
I don't know what it is
accepteula (bool, optional):
Automatically accept the Mojang EULA
Raises:
ServerStartError: When Aternos
is unable to start the server
2022-06-23 14:13:56 +03:00
"""
startreq = self.atserver_request(
f'{SERVER_URL}/start',
'GET', params={
'headstart': int(headstart),
'access-credits': int(access_credits),
},
sendtoken=True,
2022-06-23 14:13:56 +03:00
)
startresult = startreq.json()
2022-06-16 14:40:10 +03:00
2022-06-23 14:13:56 +03:00
if startresult['success']:
return
2022-07-01 09:31:23 +03:00
2022-06-23 14:13:56 +03:00
error = startresult['error']
2021-10-08 18:35:20 +03:00
2022-06-23 14:13:56 +03:00
if error == 'eula' and accepteula:
self.eula()
2022-07-01 13:28:39 +03:00
self.start(accepteula=False)
return
2022-07-01 09:31:23 +03:00
raise ServerStartError(error)
2022-06-23 14:13:56 +03:00
def confirm(self) -> None:
"""Confirms server launching"""
self.atserver_request(
f'{SERVER_URL}/confirm',
'GET', sendtoken=True,
2022-06-23 14:13:56 +03:00
)
def stop(self) -> None:
"""Stops the server"""
self.atserver_request(
f'{SERVER_URL}/stop',
'GET', sendtoken=True,
2022-06-23 14:13:56 +03:00
)
def cancel(self) -> None:
"""Cancels server launching"""
self.atserver_request(
f'{SERVER_URL}/cancel',
'GET', sendtoken=True,
2022-06-23 14:13:56 +03:00
)
def restart(self) -> None:
"""Restarts the server"""
self.atserver_request(
f'{SERVER_URL}/restart',
'GET', sendtoken=True,
2022-06-23 14:13:56 +03:00
)
def eula(self) -> None:
"""Sends a request to accept the Mojang EULA"""
2022-06-23 14:13:56 +03:00
self.atserver_request(
f'{SERVER_URL}/accept-eula',
'GET', sendtoken=True,
2022-06-23 14:13:56 +03:00
)
def files(self) -> FileManager:
"""Returns FileManager instance
for file operations
2022-06-23 14:13:56 +03:00
Returns:
FileManager object
2022-06-23 14:13:56 +03:00
"""
return FileManager(self)
def config(self) -> AternosConfig:
"""Returns AternosConfig instance
for editing server settings
2022-06-23 14:13:56 +03:00
Returns:
AternosConfig object
2022-06-23 14:13:56 +03:00
"""
return AternosConfig(self)
def players(self, lst: Lists) -> PlayersList:
"""Returns PlayersList instance
for managing operators, whitelist
and banned players lists
2022-06-23 14:13:56 +03:00
Args:
lst (Lists): Players list type,
must be the atplayers.Lists enum value
Returns:
PlayersList object
2022-06-23 14:13:56 +03:00
"""
return PlayersList(lst, self)
def set_subdomain(self, value: str) -> None:
"""Set a new subdomain for your server
(the part before `.aternos.me`)
2022-06-23 14:13:56 +03:00
Args:
value (str): Subdomain
"""
self.atserver_request(
f'{SERVER_URL}/options/set-subdomain',
'GET', params={'subdomain': value},
sendtoken=True,
)
def set_motd(self, value: str) -> None:
"""Set new Message of the Day
(shown below the name in the Minecraft servers list).
Formatting with "paragraph sign + code" is supported,
see https://minecraft.tools/color-code.php
Args:
value (str): MOTD
2022-06-23 14:13:56 +03:00
"""
self.atserver_request(
f'{SERVER_URL}/options/set-motd',
'POST', data={'motd': value},
sendtoken=True,
2022-06-23 14:13:56 +03:00
)
@property
def subdomain(self) -> str:
"""Get the server subdomain
(the part before `.aternos.me`)
2022-07-01 13:28:39 +03:00
Returns:
Subdomain
2022-07-01 13:28:39 +03:00
"""
2022-06-23 14:13:56 +03:00
atdomain = self.domain
return atdomain[:atdomain.find('.')]
@property
def motd(self) -> str:
"""Get the server message of the day
(shown below its name in Minecraft servers list)
2022-07-01 13:28:39 +03:00
Returns:
MOTD
2022-07-01 13:28:39 +03:00
"""
2022-06-23 14:13:56 +03:00
return self._info['motd']
@property
def address(self) -> str:
"""Full server address
including domain and port
2022-07-01 13:28:39 +03:00
Returns:
Server address
2022-07-01 13:28:39 +03:00
"""
return f'{self.domain}:{self.port}'
2022-06-23 14:13:56 +03:00
@property
def domain(self) -> str:
"""Server domain (e.g. `test.aternos.me`).
In other words, address without port number
2022-07-01 13:28:39 +03:00
Returns:
Domain
2022-07-01 13:28:39 +03:00
"""
2022-06-23 14:13:56 +03:00
return self._info['ip']
@property
def port(self) -> int:
2022-07-01 13:28:39 +03:00
"""Server port number
Returns:
Port
2022-07-01 13:28:39 +03:00
"""
2022-06-23 14:13:56 +03:00
return self._info['port']
@property
2022-07-01 13:28:39 +03:00
def edition(self) -> Edition:
"""Server software edition: Java or Bedrock
Returns:
Software edition
2022-07-01 13:28:39 +03:00
"""
2022-06-23 14:13:56 +03:00
soft_type = self._info['bedrock']
2022-07-01 13:28:39 +03:00
return Edition(soft_type)
2022-06-23 14:13:56 +03:00
@property
def is_java(self) -> bool:
"""Check if server software is Java Edition
Returns:
Is it Minecraft JE
"""
return not self._info['bedrock']
@property
def is_bedrock(self) -> bool:
"""Check if server software is Bedrock Edition
Returns:
Is it Minecraft BE
"""
return bool(self._info['bedrock'])
2022-06-23 14:13:56 +03:00
@property
def software(self) -> str:
2022-07-01 13:28:39 +03:00
"""Server software name (e.g. `Vanilla`)
Returns:
Software name
2022-07-01 13:28:39 +03:00
"""
2022-06-23 14:13:56 +03:00
return self._info['software']
@property
def version(self) -> str:
"""Server software version (1.16.5)
2022-07-01 13:28:39 +03:00
Returns:
Software version
2022-07-01 13:28:39 +03:00
"""
2022-06-23 14:13:56 +03:00
return self._info['version']
@property
def css_class(self) -> str:
"""CSS class for the server status element
on official web site: offline, online, loading, etc.
See https://aternos.dc09.ru/howto/server/#server-info
In most cases you need `AternosServer.status` instead of this
2022-07-01 13:28:39 +03:00
Returns:
CSS class
2022-07-01 13:28:39 +03:00
"""
2022-06-23 14:13:56 +03:00
return self._info['class']
@property
def status(self) -> str:
"""Server status string
(offline, loading, preparing)
Returns:
Status string
"""
return self._info['lang']
@property
def status_num(self) -> Status:
"""Server numeric status.
It is highly recommended to use
status string instead of a number
2022-07-01 13:28:39 +03:00
Returns:
Status code
2022-07-01 13:28:39 +03:00
"""
return Status(self._info['status'])
2022-06-23 14:13:56 +03:00
@property
def players_list(self) -> List[str]:
"""List of connected players' nicknames
2022-07-01 13:28:39 +03:00
Returns:
Connected players
2022-07-01 13:28:39 +03:00
"""
2022-06-23 14:13:56 +03:00
return self._info['playerlist']
@property
def players_count(self) -> int:
"""How many players are connected
2022-07-01 13:28:39 +03:00
Returns:
Connected players count
2022-07-01 13:28:39 +03:00
"""
2022-06-23 14:13:56 +03:00
return int(self._info['players'])
@property
def slots(self) -> int:
"""Server slots, how many
players **can** connect
2022-07-01 13:28:39 +03:00
Returns:
Slots count
2022-07-01 13:28:39 +03:00
"""
2022-06-23 14:13:56 +03:00
return int(self._info['slots'])
@property
def ram(self) -> int:
2022-07-01 13:28:39 +03:00
"""Server used RAM in MB
Returns:
Used RAM
2022-07-01 13:28:39 +03:00
"""
2022-06-23 14:13:56 +03:00
return int(self._info['ram'])
2022-12-23 16:38:51 +03:00
@property
def countdown(self) -> int:
"""Server stop countdown
in seconds
Returns:
Stop countdown
"""
value = self._info['countdown']
return int(value or -1)