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

434 lines
11 KiB
Python
Raw Normal View History

2022-07-01 13:28:39 +03:00
"""Aternos Minecraft server"""
import enum
import json
from typing import Optional, List
from requests import Response
2021-10-08 18:35:20 +03:00
2022-03-18 17:38:36 +03:00
from .atconnect import AternosConnect
2022-07-01 09:31:23 +03:00
from .aterrors import ServerStartError
2022-03-18 17:38:36 +03:00
from .atfm import FileManager
from .atconf import AternosConfig
from .atplayers import PlayersList
2022-06-16 14:40:10 +03:00
from .atplayers import Lists
2022-01-22 14:10:30 +03:00
from .atwss import AternosWss
2022-06-23 14:13:56 +03:00
2022-03-18 17:38:36 +03:00
class Edition(enum.IntEnum):
2022-06-16 14:40:10 +03:00
2022-06-23 14:13:56 +03:00
"""Server edition type enum"""
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
starting = 2
shutdown = 3
unknown = 6
error = 7
confirm = 10
2022-06-16 14:40:10 +03:00
2021-10-08 18:35:20 +03:00
class AternosServer:
2022-06-23 14:13:56 +03:00
"""Class for controlling your Aternos Minecraft server
:param servid: Unique server IDentifier
:type servid: str
:param atconn: :class:`python_aternos.atconnect.AternosConnect`
instance with initialized Aternos session
:type atconn: python_aternos.atconnect.AternosConnect
:param reqinfo: Automatically call AternosServer.fetch()
to get all info, defaults to `True`
:type reqinfo: bool, optional
"""
def __init__(
self, servid: str,
atconn: AternosConnect,
reqinfo: bool = True) -> None:
self.servid = servid
self.atconn = atconn
if reqinfo:
self.fetch()
def fetch(self) -> None:
"""Send a request to Aternos API to get all server info"""
servreq = self.atserver_request(
'https://aternos.org/panel/ajax/status.php',
'GET', sendtoken=True
)
self._info = json.loads(servreq.content)
def wss(self, autoconfirm: bool = False) -> AternosWss:
"""Returns :class:`python_aternos.atwss.AternosWss`
instance for listening server streams in real-time
:param autoconfirm: Automatically start server status listener
when AternosWss connects to API to confirm
server launching, defaults to `False`
:type autoconfirm: bool, optional
:return: :class:`python_aternos.atwss.AternosWss` object
:rtype: python_aternos.atwss.AternosWss
"""
return AternosWss(self, autoconfirm)
2022-07-01 13:28:39 +03:00
def start(
self,
headstart: bool = False,
accepteula: bool = True) -> None:
2022-06-23 14:13:56 +03:00
"""Starts a server
:param headstart: Start a server in the headstart mode
which allows you to skip all queue, defaults to `False`
:type headstart: bool, optional
:param accepteula: Automatically accept
the Mojang EULA, defaults to `True`
:type accepteula: bool, optional
2022-07-01 09:31:23 +03:00
:raises ServerStartError: When Aternos
is unable to start the server
2022-06-23 14:13:56 +03:00
"""
startreq = self.atserver_request(
'https://aternos.org/panel/ajax/start.php',
'GET', params={'headstart': int(headstart)},
sendtoken=True
)
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:
2021-10-08 18:35:20 +03:00
2022-06-23 14:13:56 +03:00
"""Confirms server launching"""
self.atserver_request(
'https://aternos.org/panel/ajax/confirm.php',
'GET', sendtoken=True
)
def stop(self) -> None:
"""Stops the server"""
self.atserver_request(
'https://aternos.org/panel/ajax/stop.php',
'GET', sendtoken=True
)
def cancel(self) -> None:
"""Cancels server launching"""
self.atserver_request(
'https://aternos.org/panel/ajax/cancel.php',
'GET', sendtoken=True
)
def restart(self) -> None:
"""Restarts the server"""
self.atserver_request(
'https://aternos.org/panel/ajax/restart.php',
'GET', sendtoken=True
)
def eula(self) -> None:
"""Accepts the Mojang EULA"""
self.atserver_request(
'https://aternos.org/panel/ajax/eula.php',
'GET', sendtoken=True
)
def files(self) -> FileManager:
"""Returns :class:`python_aternos.atfm.FileManager`
instance for file operations
:return: :class:`python_aternos.atfm.FileManager` object
:rtype: python_aternos.atfm.FileManager
"""
return FileManager(self)
def config(self) -> AternosConfig:
"""Returns :class:`python_aternos.atconf.AternosConfig`
instance for editing server settings
:return: :class:`python_aternos.atconf.AternosConfig` object
:rtype: python_aternos.atconf.AternosConfig
"""
return AternosConfig(self)
def players(self, lst: Lists) -> PlayersList:
"""Returns :class:`python_aternos.atplayers.PlayersList`
instance for managing operators, whitelist and banned players lists
:param lst: Players list type, must be
the :class:`python_aternos.atplayers.Lists` enum value
:type lst: python_aternos.atplayers.Lists
:return: :class:`python_aternos.atplayers.PlayersList`
:rtype: python_aternos.atplayers.PlayersList
"""
return PlayersList(lst, self)
def atserver_request(
self, url: str, method: str,
params: Optional[dict] = None,
data: Optional[dict] = None,
headers: Optional[dict] = None,
sendtoken: bool = False) -> Response:
"""Sends a request to Aternos API
with server IDenitfier parameter
:param url: Request URL
:type url: str
:param method: Request method, must be GET or POST
:type method: str
:param params: URL parameters, defaults to None
:type params: Optional[dict], optional
:param data: POST request data, if the method is GET,
this dict will be combined with params, defaults to None
:type data: Optional[dict], optional
:param headers: Custom headers, defaults to None
:type headers: Optional[dict], optional
:param sendtoken: If the ajax and SEC token
should be sent, defaults to False
:type sendtoken: bool, optional
:return: API response
:rtype: requests.Response
"""
return self.atconn.request_cloudflare(
url=url, method=method,
params=params, data=data,
headers=headers,
reqcookies={
'ATERNOS_SERVER': self.servid
},
sendtoken=sendtoken
)
@property
def subdomain(self) -> str:
2022-07-01 13:28:39 +03:00
"""Server subdomain (part of domain before `.aternos.me`)
:return: Subdomain
:rtype: str
"""
2022-06-23 14:13:56 +03:00
atdomain = self.domain
return atdomain[:atdomain.find('.')]
@subdomain.setter
def subdomain(self, value: str) -> None:
2022-07-01 13:28:39 +03:00
"""Set new subdomain for your server
:param value: Subdomain
:type value: str
"""
2022-06-23 14:13:56 +03:00
self.atserver_request(
'https://aternos.org/panel/ajax/options/subdomain.php',
'GET', params={'subdomain': value},
sendtoken=True
)
@property
def motd(self) -> str:
2022-07-01 13:28:39 +03:00
"""Server message of the day,
which is shown below its name in the servers list
:return: MOTD
:rtype: str
"""
2022-06-23 14:13:56 +03:00
return self._info['motd']
@motd.setter
def motd(self, value: str) -> None:
2022-07-01 13:28:39 +03:00
"""Set new message of the day
:param value: MOTD
:type value: str
"""
2022-06-23 14:13:56 +03:00
self.atserver_request(
'https://aternos.org/panel/ajax/options/motd.php',
'POST', data={'motd': value},
sendtoken=True
)
@property
def address(self) -> str:
2022-07-01 13:28:39 +03:00
"""Full server address including domain and port
:return: Server address
:rtype: str
"""
2022-06-23 14:13:56 +03:00
return self._info['displayAddress']
@property
def domain(self) -> str:
2022-07-01 13:28:39 +03:00
"""Server domain (test.aternos.me),
address without port number
:return: Domain
:rtype: str
"""
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
:return: Port
:rtype: int
"""
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
:return: Software edition
:rtype: Edition
"""
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 software(self) -> str:
2022-07-01 13:28:39 +03:00
"""Server software name (e.g. `Vanilla`)
:return: Software name
:rtype: str
"""
2022-06-23 14:13:56 +03:00
return self._info['software']
@property
def version(self) -> str:
2022-07-01 13:28:39 +03:00
"""Server software version (e.g. `1.16.5`)
:return: Software version
:rtype: str
"""
2022-06-23 14:13:56 +03:00
return self._info['version']
@property
def status(self) -> str:
2022-07-01 13:28:39 +03:00
"""Server status string (offline, loading)
:return: Status string
:rtype: str
"""
2022-06-23 14:13:56 +03:00
return self._info['class']
@property
def status_num(self) -> int:
2022-07-01 13:28:39 +03:00
"""Server numeric status. It is highly recommended
to use status string instead of a number.
:return: Status code
:rtype: Status
"""
return Status(self._info['status'])
2022-06-23 14:13:56 +03:00
@property
def players_list(self) -> List[str]:
2022-07-01 13:28:39 +03:00
"""List of connected players nicknames
:return: Connected players
:rtype: List[str]
"""
2022-06-23 14:13:56 +03:00
return self._info['playerlist']
@property
def players_count(self) -> int:
2022-07-01 13:28:39 +03:00
"""How many connected players
:return: Connected players count
:rtype: int
"""
2022-06-23 14:13:56 +03:00
return int(self._info['players'])
@property
def slots(self) -> int:
2022-07-01 13:28:39 +03:00
"""Server slots, how many players can connect
:return: Slots count
:rtype: int
"""
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
:return: Used RAM
:rtype: int
"""
2022-06-23 14:13:56 +03:00
return int(self._info['ram'])