Source code for ogu_api.resources.session
from __future__ import annotations
from typing import Any, Mapping
import tls_client.response
from ._base import ResourceBase
__all__ = ['SessionResource']
[docs]
class SessionResource(ResourceBase):
"""Login, logout, and the public landing page.
Wraps ``/member.php?action=login`` (form + submit) and
``/member.php?action=logout``. The session cookie (``ogusid``) ends up on
the client's cookie jar after a successful login.
"""
[docs]
async def get_home(self) -> tls_client.response.Response:
"""Fetch the forum landing page (``/index.php``).
Returns:
Raw response. Useful for sanity-checking the session
(``len(response.text)`` should be substantial when logged in).
"""
return await self._http.get('/index.php')
[docs]
async def get_login_page(self) -> tls_client.response.Response:
"""Fetch the login form page (``/member.php?action=login``).
Returns:
Raw response. Pass ``response.text`` to
:meth:`extract_login_hidden` to recover the CSRF / hidden fields
when calling :meth:`login` manually.
"""
return await self._http.get('/member.php?action=login', allow_redirects = True)
[docs]
async def login(
self,
username: str,
password: str,
two_factor: str = '',
*,
hidden: Mapping[str, Any] | None = None,
) -> tls_client.response.Response:
"""Submit the login form and capture the session cookie.
When ``hidden`` is omitted, the SDK first GETs
``/member.php?action=login`` and extracts the hidden fields itself, so
most callers just pass username + password.
Args:
username: Forum username.
password: Forum password.
two_factor: Current TOTP code. Empty string if 2FA is disabled.
hidden: Pre-fetched hidden form fields. Skips the extra round-trip.
Returns:
Raw POST response. The ``ogusid`` session cookie is set on
``client.cookies`` automatically on success.
Example:
>>> await client.session.login('username', 'password')
>>> await client.session.login('username', 'password', '123456')
"""
if hidden is None:
page = await self.get_login_page()
hidden = self.extract_login_hidden(page.text)
return await self._http.post(
'/member.php?action=login',
data = {
**hidden,
'username': username,
'password': password,
'2facode': two_factor,
},
allow_redirects = False,
)
[docs]
async def logout(self, logout_key: str | None = None) -> tls_client.response.Response:
"""End the current session.
OGU's logout requires a ``logoutkey`` query parameter. When omitted,
the SDK fetches the home page and extracts it from the logout link.
Args:
logout_key: Pre-fetched key. Skips the extra round-trip when
provided.
Returns:
Raw GET response. The session cookies are invalidated server-side.
"""
if logout_key is None:
home = await self.get_home()
logout_key = self.extract_logout_key(home.text) or ''
return await self._http.get(
f'/member.php?action=logout&logoutkey={logout_key}',
allow_redirects = False,
)