__version__ = "0.1.0" from urllib.parse import urljoin from typing import Optional, Union import requests # Exceptions class LimitExceeded(Exception): pass class QueryTimeout(Exception): pass class BadRequest(Exception): pass class ServerSeeker: def __init__(self, api_key: str, endpoint: str = "https://api.serverseeker.net"): self.endpoint = endpoint self.session = requests.Session() self.session.headers.update({"Authorization": "Bearer " + api_key}) self.session.headers.update({"User-Agent": f"ServerSeeker.py/{__version__} +https://git.magmaus3.eu.org/magmaus3/serverseeker.py"}) def server_info(self, ip: str, port: int = 25565) -> dict: """ Gives you info about a server. """ rq = self.session.post( urljoin(self.endpoint, "/server_info"), json={"ip": ip, "port": port} ) if not rq.ok: if rq.status_code == 400: raise BadRequest(rq.json()["error"]) elif rq.status_code == 429: raise LimitExceeded(rq.json()["error"]) elif rq.status_code == 504: raise QueryTimeout(rq.json()["error"]) return rq.json() def servers(self, country_code: Optional[str] = None, max_players: Optional[int] = None, online_players: Optional[Union[tuple[Union[int, str], Union[int, str]], int]] = None, protocol: Optional[int] = None, software: Optional[str] = None, cracked: Optional[bool] = None, description: Optional[str] = None, asn: Optional[int] = None, ignore_modded: Optional[bool] = None, only_bungeespoofable: Optional[bool] = None ) -> list: """ Gives you a list of servers (with matching criteria). Limited to 100 results. """ rq = self.session.post( urljoin(self.endpoint, "/servers"), json={ "asn": asn, "country_code": country_code, "cracked": cracked, "description": description, "ignore_modded": ignore_modded, "max_players": max_players, "online_players": online_players, "only_bungeespoofable": only_bungeespoofable, "protocol": protocol, "software": software } ) if not rq.ok: try: if rq.status_code == 400: raise BadRequest(rq.json()["error"]) elif rq.status_code == 429: raise LimitExceeded(rq.json()["error"]) elif rq.status_code == 504: raise QueryTimeout(rq.json()["error"]) except: raise Exception(rq.text) return rq.json() def stats(self) -> dict: """ Gives you stats about ServerSeeker. Somewhat inaccurate. """ rq = self.session.get( urljoin(self.endpoint, "/stats") ) return rq.json() def user_info(self) -> dict: """ Gives you information about your account (user id, username, avatar url). Also gives you information about your rate limits. Rate limits reset at midnight UTC. """ rq = self.session.post( urljoin(self.endpoint, "/user_info") ) if not rq.ok: if rq.status_code == 400: raise BadRequest(rq.json()["error"]) return rq.json() def whereis(self, name: Optional[str] = None, uuid: Optional[str] = None) -> dict: """ Gives you a list of servers where a player was. Limited to 1000 results. **Attention: You must use name OR uuid as your parameter, not both!** """ if name and not uuid: data = {"name": name} elif uuid and not name: data = {"uuid": uuid} else: raise ValueError("You can only provide name or uuid, not both") rq = self.session.post( urljoin(self.endpoint, "/whereis"), json=data ) if not rq.ok: if rq.status_code == 400: raise BadRequest(rq.json()["error"]) elif rq.status_code == 429: raise LimitExceeded(rq.json()["error"]) elif rq.status_code == 504: raise QueryTimeout(rq.json()["error"]) return rq.json()