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/atfm.py
DarkCat09 4892430f19 MkDocs, Readme, Files API, Automated session saving, v2.0.1
MkDocs: sphinx docstrings rewritten to google, improved config, written the major part of how-to.
Readme: centered title + logo, added badges, features list, updated changelog.

Improved Files API, added automatical session saving and restoring to Client.
Some changes in makefile and gitignore.
License Notice now refers to all contributors.
2022-08-26 16:14:07 +04:00

199 lines
5.2 KiB
Python

"""Exploring files in your server directory"""
from typing import Union, Optional, Any, List
from typing import TYPE_CHECKING
import lxml.html
from .atfile import AternosFile, FileType
if TYPE_CHECKING:
from .atserver import AternosServer
class FileManager:
"""Aternos file manager class
for viewing files structure"""
def __init__(self, atserv: 'AternosServer') -> None:
"""Aternos file manager class
for viewing files structure
Args:
atserv (python_aternos.atserver.AternosServer):
atserver.AternosServer instance
"""
self.atserv = atserv
def list_dir(self, path: str = '') -> List[AternosFile]:
"""Requests a list of files
in the specified directory
Args:
path (str, optional):
Directory (an empty string means root)
Returns:
List of atfile.AternosFile objects
"""
path = path.lstrip('/')
filesreq = self.atserv.atserver_request(
f'https://aternos.org/files/{path}', 'GET'
)
filestree = lxml.html.fromstring(filesreq.content)
fileslist = filestree.xpath(
'//div[@class="file" or @class="file clickable"]'
)
files = []
for f in fileslist:
ftype_raw = f.xpath('@data-type')[0]
fsize = self.extract_size(
f.xpath('./div[@class="filesize"]')
)
rm_btn = f.xpath('./div[contains(@class,"js-delete-file")]')
dl_btn = f.xpath('./div[contains(@class,"js-download-file")]')
clickable = 'clickable' in f.classes
is_config = ('server.properties' in path) or ('level.dat' in path)
files.append(
AternosFile(
atserv=self.atserv,
path=f.xpath('@data-path')[0],
rmable=(len(rm_btn) > 0),
dlable=(len(dl_btn) > 0),
editable=(clickable and not is_config),
ftype={'file': FileType.file}.get(
ftype_raw, FileType.dir
),
size=fsize
)
)
return files
def extract_size(self, fsize_raw: List[Any]) -> float:
"""Parses file size from the LXML tree
Args:
fsize_raw (List[Any]): XPath parsing result
Returns:
File size in bytes
"""
if len(fsize_raw) > 0:
fsize_text = fsize_raw[0].text.strip()
fsize_num = fsize_text[:fsize_text.rfind(' ')]
fsize_msr = fsize_text[fsize_text.rfind(' ') + 1:]
try:
return self.convert_size(
float(fsize_num),
fsize_msr
)
except ValueError:
return -1.0
return 0.0
def convert_size(
self,
num: Union[int, float],
measure: str) -> float:
"""Converts "human" file size to size in bytes
Args:
num (Union[int,float]): Size
measure (str): Units (B, kB, MB, GB)
Returns:
Size in bytes
"""
measure_match = {
'B': 1,
'kB': 1000,
'MB': 1000000,
'GB': 1000000000
}
return measure_match.get(measure, -1) * num
def get_file(self, path: str) -> Optional[AternosFile]:
"""Returns :class:`python_aternos.atfile.AternosFile`
instance by its path
Args:
path (str): Path to the file including its filename
Returns:
atfile.AternosFile object
if file has been found,
otherwise None
"""
filedir = path[:path.rfind('/')]
filename = path[path.rfind('/'):]
files = self.list_dir(filedir)
return {
'file': f
for f in files
if f.name == filename
}.get('file', None)
def dl_file(self, path: str) -> bytes:
"""Returns the file content in bytes (downloads it)
Args:
path (str): Path to file including its filename
Returns:
File content
"""
file = self.atserv.atserver_request( # type: ignore
'https://aternos.org/panel/ajax/files/download.php'
'GET', params={
'file': path.replace('/', '%2F')
}
)
return file.content
def dl_world(self, world: str = 'world') -> bytes:
"""Returns the world zip file content
by its name (downloads it)
Args:
world (str, optional): Name of world
Returns:
ZIP file content
"""
resp = self.atserv.atserver_request( # type: ignore
'https://aternos.org/panel/ajax/worlds/download.php'
'GET', params={
'world': world.replace('/', '%2F')
}
)
return resp.content