import aiohttp from . import exceptions from . import logs from . import schemas from . import settings def get_session_kwargs(): headers = {"User-Agent": settings.USER_AGENT} return { "timeout": aiohttp.ClientTimeout(total=settings.TIMEOUT), "headers": headers, } def get_session(): kwargs = get_session_kwargs() return aiohttp.ClientSession(**kwargs) async def fetch_nodeinfo(session, domain, protocol="https"): nodeinfo = await get_well_known_data(session, domain=domain, protocol=protocol) data = await get_nodeinfo(session, nodeinfo) return data async def get_well_known_data(session, domain, protocol="https"): url = f"https://{domain}/.well-known/nodeinfo" response = await session.get(url) return await response.json() async def get_nodeinfo(session, nodeinfo): for link in nodeinfo.get("links", []): if link["rel"] == "http://nodeinfo.diaspora.software/ns/schema/2.0": response = await session.get(link["href"]) return await response.json() raise exceptions.NoNodeInfo() def clean_nodeinfo(data): schema = schemas.NodeInfo2Schema() result = schema.load(data) return result.data async def get_jwt_token(session, url, username, password): url = f"{url}/api/v1/token/" response = await session.post( url, data={"username": username, "password": password} ) if response.status == 400: raise exceptions.AuthenticationError( "Unable to log in with provided credentials" ) return (await response.json())["token"] class API(object): def __init__(self, base_url, token): self.base_url = base_url self.token = token self._session = None async def __aenter__(self): self._session = get_session() await self._session.__aenter__() async def __aexit__(self, exc_type, exc, tb): if self._session: await self._session.__aexit__(exc_type, exc, tb) self._session = None def request(self, method, path, *args, **kwargs): if path.startswith("http://") or path.startswith("https://"): full_url = path else: full_url = self.base_url + path headers = kwargs.setdefault("headers", {}) if self.token: headers["Authorization"] = "JWT {}".format(self.token) handler = getattr(self._session, method) return handler(full_url, *args, **kwargs) def get_api(domain, protocol, token=None): url = "{}://{}/".format(protocol, domain) return API(url, token=token)