Source code for ogu_api.resources.reputation

from __future__ import annotations

from typing import Any, Mapping

import tls_client.response

from ..errors import OGUReputationError
from ..models import ReputationPage
from ._base import ResourceBase

__all__ = ['ReputationResource']


[docs] class ReputationResource(ResourceBase): """Send reputation to a user. Paths: - ``/reputation.php?action=add&uid={uid}&pid=0&modal=1`` — modal form. - ``/reputation.php?modal=1`` (POST) — submit. """
[docs] async def get_page_response(self, user_id: str | int) -> tls_client.response.Response: """Fetch the raw reputation modal for a target user (no parsing).""" return await self._http.get( f'/reputation.php?action=add&uid={user_id}&pid=0&modal=1', )
[docs] async def get_page(self, user_id: str | int) -> ReputationPage: """Fetch the reputation modal and return the parsed form data. Args: user_id: Target user id. Returns: :class:`~ogu_api.ReputationPage` with ``values`` (allowed reputation amounts as strings, e.g. ``('-1', '0', '1')``) and ``hidden`` (CSRF / form fields). Note: ``values`` is empty when the target won't accept reputation from the current account (e.g. yourself, or someone you've already repped recently). """ response = await self.get_page_response(user_id) html = response.text return ReputationPage( values = tuple(self.extract_values(html)), hidden = self.extract_hidden(html), )
[docs] async def send( self, reputation: int, comment: str, uid: str | int = '', *, hidden: Mapping[str, Any] | None = None, validate: bool = True, ) -> tls_client.response.Response: """Submit a reputation rating. When ``hidden`` is omitted, the SDK first loads the rep modal for ``uid`` to recover the form fields. With ``validate=True`` (default), it also checks that ``reputation`` appears in the modal's allowed ``<select id="reputation">`` options before submitting. Args: reputation: ``-1``, ``0``, or ``1`` — depending on what the target's modal allows. comment: Comment attached to the rating. uid: Target user id. hidden: Pre-fetched hidden form fields. validate: Validate ``reputation`` against the modal's allowed values before posting. Set to ``False`` to skip the GET. Returns: Raw POST response. The body containing ``"Your reputation rating has successfully been added"`` indicates success. Raises: OGUReputationError: ``validate=True`` and ``reputation`` is not in the target's allowed values. Example: >>> await client.reputation.send( ... reputation = 1, ... comment = 'good trade', ... uid = 12345, ... ) """ if hidden is None or validate: page = await self.get_page(uid) if validate and str(reputation) not in page.values: raise OGUReputationError( f'Invalid reputation value {reputation!r} for uid {uid}', valid_amounts = list(page.values), ) if hidden is None: hidden = page.hidden return await self._http.post( '/reputation.php?modal=1', data = { **hidden, 'reputation': reputation, 'comments': comment, 'uid': uid, }, )
[docs] @staticmethod def extract_values(page_html: str) -> list[str]: """Pull the allowed reputation values from ``<select id="reputation">``.""" soup = ResourceBase._soup(page_html) select = soup.find('select', id = 'reputation') if not select: return [] return [ option.get('value') for option in select.find_all('option') ]
[docs] @staticmethod def extract_hidden(page_html: str) -> dict[str, Any]: """Pull hidden inputs off the reputation form (``form[action="reputation.php"]``).""" return ResourceBase._extract_hidden(page_html, form_selector = 'form[action="reputation.php"]')