Source code for jsktoolbox.edmctool.edsm

# -*- coding: utf-8 -*-
"""
Author:  Jacek 'Szumak' Kotlarski --<szumak@virthost.pl>
Created: 2024-10-08

Purpose: EDSM API client classes.
"""

import requests  # type: ignore
import json

from typing import Dict, List, Optional, Any, Union
from requests.utils import requote_uri  # type: ignore
from inspect import currentframe

from .edsm_keys import EdsmKeys


from ..basetool import BData
from ..attribtool import ReadOnlyClass
from ..raisetool import Raise
from ..edmctool.stars import StarsSystem


class _Keys(object, metaclass=ReadOnlyClass):
    """Internal  keys container class."""

    OPTIONS: str = "__options__"
    SYSTEMS_URL: str = "__systems_url__"
    SYSTEM_URL: str = "__system_url__"


[docs] class Url(BData): """Url. Class for serving HTTP/HTTPS requests. """
[docs] def __init__(self) -> None: """Create Url helper object.""" self.__options = { EdsmKeys.SHOW_ID: 1, EdsmKeys.SHOW_PERMIT: 1, EdsmKeys.SHOW_COORDINATES: 1, EdsmKeys.SHOW_INFORMATION: 0, EdsmKeys.SHOW_PRIMARY_STAR: 0, EdsmKeys.INCLUDE_HIDDEN: 0, } self._set_data( key=_Keys.SYSTEMS_URL, value="https://www.edsm.net/api-v1/", set_default_type=str, ) self._set_data( key=_Keys.SYSTEM_URL, value="https://www.edsm.net/api-system-v1/", set_default_type=str, )
@property def __options(self) -> Dict: """Return the options dictionary for URL parameters. ### Returns: Dict - URL query options mapping. """ return self._get_data(key=_Keys.OPTIONS) # type: ignore @__options.setter def __options(self, value: Optional[Dict]) -> None: """Assign the options dictionary. ### Arguments: * value: Optional[Dict] - Options dictionary or None to initialize empty. """ if value is None: self._set_data(key=_Keys.OPTIONS, value={}, set_default_type=Dict) else: self._set_data(key=_Keys.OPTIONS, value=value, set_default_type=Dict) @property def __system_url(self) -> str: """Return the system API endpoint URL. ### Returns: str - URL for single system queries. """ return self._get_data(key=_Keys.SYSTEM_URL) # type: ignore @property def __systems_url(self) -> str: """Return the systems API endpoint URL. ### Returns: str - URL for multiple systems queries. """ return self._get_data(key=_Keys.SYSTEMS_URL) # type: ignore @property def options(self) -> str: """Get url options string. ### Returns: str - Formatted URL parameter string. """ out: str = "" for key, value in self.__options.items(): out += f"&{key}={value}" return out
[docs] def bodies_url(self, s_system: StarsSystem) -> str: """Returns proper API url for getting bodies information data. ### Arguments: * s_system: StarsSystem - System object containing name or address. ### Returns: str - Formatted URL for bodies query. ### Raises: * TypeError: If s_system is not a StarsSystem instance. """ if not isinstance(s_system, StarsSystem): raise Raise.error( f"StarsSystem type expected, '{type(s_system)}' received", TypeError, self._c_name, currentframe(), ) if s_system.name: return requote_uri(f"{self.__system_url}bodies?systemName={s_system.name}") if s_system.address: return requote_uri(f"{self.__system_url}bodies?systemId={s_system.address}") return ""
[docs] def system_url(self, s_system: StarsSystem) -> str: """Returns proper API url for getting system data. ### Arguments: * s_system: StarsSystem - System object containing name. ### Returns: str - Formatted URL for system query. ### Raises: * TypeError: If s_system is not a StarsSystem instance. """ if not isinstance(s_system, StarsSystem): raise Raise.error( f"StarsSystem type expected, '{type(s_system)}' received", TypeError, self._c_name, currentframe(), ) if s_system.name: return requote_uri( f"{self.__systems_url}system?systemName={s_system.name}{self.options}" ) return ""
[docs] def radius_url(self, s_system: StarsSystem, radius: int) -> str: """Returns proper API url for getting systems data in radius. ### Arguments: * s_system: StarsSystem - System object containing name. * radius: int - Search radius in light years (clamped to 5-100). ### Returns: str - Formatted URL for sphere-systems query. ### Raises: * TypeError: If s_system is not a StarsSystem instance. """ if not isinstance(s_system, StarsSystem): raise Raise.error( f"StarsSystem type expected, '{type(s_system)}' received", TypeError, self._c_name, currentframe(), ) if not isinstance(radius, int): radius = 50 else: if radius < 5: radius = 5 elif radius > 100: radius = 100 if s_system.name: return requote_uri( f"{self.__systems_url}sphere-systems?systemName={s_system.name}&radius={radius}{self.options}" ) return ""
[docs] def cube_url(self, s_system: StarsSystem, size: int) -> str: """Returns proper API url for getting systems data in cube. ### Arguments: * s_system: StarsSystem - System object containing name. * size: int - Cube size in light years (clamped to 10-200). ### Returns: str - Formatted URL for cube-systems query. ### Raises: * TypeError: If s_system is not a StarsSystem instance. """ if not isinstance(s_system, StarsSystem): raise Raise.error( f"StarsSystem type expected, '{type(s_system)}' received", TypeError, self._c_name, currentframe(), ) if not isinstance(size, int): size = 100 else: if size < 10: size = 10 elif size > 200: size = 200 if s_system.name: return requote_uri( f"{self.__systems_url}cube-systems?systemName={s_system.name}&size={size}{self.options}" ) return ""
[docs] def system_query(self, s_system: StarsSystem) -> Optional[Dict]: """Returns result of query for system data. ### Arguments: * s_system: StarsSystem - System object containing name. ### Returns: Optional[Dict] - System data from EDSM API or None on failure. ### Raises: * TypeError: If s_system is not a StarsSystem instance. """ if not isinstance(s_system, StarsSystem): raise Raise.error( f"StarsSystem type expected, '{type(s_system)}' received", TypeError, self._c_name, currentframe(), ) url: str = self.system_url(s_system) if not url: return None try: response: requests.Response = requests.get(url, timeout=30) if response.status_code != 200: print(f"Error calling API for system data: {response.status_code}") return None return json.loads(response.text) except Exception as ex: print(ex) return None
[docs] def url_query(self, url: str) -> Union[List[Dict[str, Any]], Dict[str, Any]]: """Returns result of query for url. ### Arguments: * url: str - Full API URL to query. ### Returns: Union[List[Dict[str, Any]], Dict[str, Any]] - Response data from EDSM API or empty list on failure. """ out = [] if not url: return out try: response: requests.Response = requests.get(url, timeout=60) if response.status_code != 200: print(f"Error calling API for EDSM data: {response.status_code}") else: out = json.loads(response.text) except Exception as ex: print(ex) return out
# #[EOF]#######################################################################