Async Python wrapper for the OGUsers (oguser.com) forum.
Project description
ogu-api
An async Python wrapper for the OGUsers forum.
Wraps the public-facing pages and forms; login, profile lookup, reputation, credits, private messages, feed, threads, notifications, member search, account control panel, with a typed, async-first client.
Install
pip install ogu-api
Requires Python 3.11+.
Quick start
import asyncio
from ogu_api import OGUClient
async def main() -> None:
async with OGUClient() as client:
await login(client, 'username', 'password')
user = await client.users.get_by_username('forgivenforget')
print(user.username, user.credits, user.reputation, user.vouches)
async def login(client: OGUClient, username: str, password: str, two_factor: str = '') -> None:
page = await client.session.get_login_page()
hidden = client.session.extract_login_hidden(page.text)
await client.session.login(username, password, two_factor, **hidden)
asyncio.run(main())
Resources
| Resource | What it covers |
|---|---|
client.session |
login page, login, logout |
client.users |
profile lookup by username or uid; returns UserProfile (id, username, reputation, vouches, credits) |
client.usercp |
notepad, signature, options, profile, change username/password/email |
client.reputation |
reputation page, send reputation |
client.credits |
donate page, stats page, send credits, parse recently-sent transactions |
client.messages |
PM inbox, conversation, compose, send, tracking, delete |
client.notifications |
notifications page, alerts, mark alerts read |
client.feed |
explore feed, home feed, thread-id extraction |
client.threads |
view thread, view forum, reply, create thread |
client.search |
full-text search form + post |
client.members |
member list, top, statistics, team, groups, vouches, awards, reputation history |
Send a PM
Most authenticated POSTs need a my_post_key. Pull it off whatever page you're already loading — here, the compose page:
compose = await client.messages.get_compose_page()
await client.messages.send(
to = 'recipient',
message = 'hello',
my_post_key = client.messages.extract_my_post_key(compose.text),
)
Read the feed
explore = await client.feed.get_explore()
for link in client.feed.extract_thread_links(explore.text)[:5]:
thread = await client.threads.get_by_link(link)
print(thread.text[:200])
extract_thread_links returns paths for both numeric (/showthread.php?tid=1234) and slug-rewritten (/Thread-Some-Slug) thread URLs. If you specifically need numeric thread IDs, use extract_thread_ids — it skips slug-only links.
Reply to a thread
reply_page = await client.threads.get_reply_page(tid)
hidden = client.threads.extract_reply_hidden(reply_page.text)
await client.threads.reply(
tid,
message = 'great post',
my_post_key = hidden['my_post_key'],
post_hash = hidden.get('posthash', ''),
)
Persist a session
ogu-api doesn't store credentials. After login, the session lives on the client's cookie jar — serialize it however you like:
cookies = {cookie.name: cookie.value for cookie in client.cookies}
To resume a session, pre-seed the cookies on a fresh client:
client = OGUClient()
for name, value in cookies.items():
client.cookies.set(name, value)
Configuration
client = OGUClient(
proxy = 'user:pass@host:8080',
timeout_seconds = 30.0,
max_retries = 3,
retry_backoff_seconds = 0.5,
client_identifier = 'chrome131',
)
Proxy strings accept user:pass@host:port, host:port:user:pass, or plain host:port and are normalized to http://... for the underlying tls_client session.
Errors
from ogu_api import OGUNotFoundError, OGURateLimitError
try:
await client.users.get_by_username('does-not-exist')
except OGUNotFoundError as E:
print('not found:', E.url)
except OGURateLimitError as E:
print('rate limited, retry after', E.retry_after_seconds)
Full hierarchy:
OGUErrorOGUAPIError—OGUAuthenticationError,OGUAuthorizationError,OGUNotFoundError,OGUValidationError,OGURateLimitError,OGUServerErrorOGUNetworkError—OGUTimeoutErrorOGUParseError,OGUSessionError,OGULoginError,OGUReputationError,OGUCreditsError
Captcha
Sending credits requires an hCaptcha token. ogu-api doesn't ship a solver — pass a pre-solved token in:
page = await client.credits.get_donate_page()
await client.credits.send(
username = 'recipient',
amount = 100,
captcha_token = solved_token,
**client.credits.extract_hidden(page.text),
)
Features
- Async-first — every request is
async, backed bytls_clienton a worker thread for Cloudflare-friendly TLS fingerprints - Typed —
from __future__ import annotationseverywhere,py.typedmarker, dataclass models for parsed payloads - Resource-oriented — calls grouped under
client.session,client.users,client.messages, etc. - Typed errors — full exception hierarchy mapped from HTTP status codes
- Retries — exponential backoff on
429and5xx, honorsRetry-After - Proxies — string-form proxies auto-normalized
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ogu_api-0.3.0.tar.gz.
File metadata
- Download URL: ogu_api-0.3.0.tar.gz
- Upload date:
- Size: 13.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f38bcb468b3a1fbd28622c9a60f0c7e9827090a0b38d559fde7de6608567fad
|
|
| MD5 |
ffcad584500ba0334f80ecbecb56d250
|
|
| BLAKE2b-256 |
219abb4cc2da184a3a2fc78b8990ca98a38c4a07ea3acc5dcf289a32627599d0
|
Provenance
The following attestation bundles were made for ogu_api-0.3.0.tar.gz:
Publisher:
publish.yml on forgivenforget/ogu-api
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ogu_api-0.3.0.tar.gz -
Subject digest:
2f38bcb468b3a1fbd28622c9a60f0c7e9827090a0b38d559fde7de6608567fad - Sigstore transparency entry: 1453602949
- Sigstore integration time:
-
Permalink:
forgivenforget/ogu-api@fced5d2f79a895a22cc7d315dec829f9a92bcfa1 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/forgivenforget
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fced5d2f79a895a22cc7d315dec829f9a92bcfa1 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ogu_api-0.3.0-py3-none-any.whl.
File metadata
- Download URL: ogu_api-0.3.0-py3-none-any.whl
- Upload date:
- Size: 22.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de2166914c05251e28e3693f7aa0a6fd9b01b5eddc24a986e881069e084ce9cd
|
|
| MD5 |
30aa075eb8bc6375f88d7f4d121eda6e
|
|
| BLAKE2b-256 |
2acefa56dc70abc7c9a358de0e9dbacddad852121fa15bd78505395454a32d0f
|
Provenance
The following attestation bundles were made for ogu_api-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on forgivenforget/ogu-api
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ogu_api-0.3.0-py3-none-any.whl -
Subject digest:
de2166914c05251e28e3693f7aa0a6fd9b01b5eddc24a986e881069e084ce9cd - Sigstore transparency entry: 1453603011
- Sigstore integration time:
-
Permalink:
forgivenforget/ogu-api@fced5d2f79a895a22cc7d315dec829f9a92bcfa1 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/forgivenforget
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fced5d2f79a895a22cc7d315dec829f9a92bcfa1 -
Trigger Event:
push
-
Statement type: