Initial commit: add Gitea PyPI publish workflow
This commit is contained in:
184
README.md
Normal file
184
README.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# conduit-client
|
||||
|
||||
A typed Python client for the [Conduit](https://conduit.librewiki.org/doku.php?id=examples) unified API gateway.
|
||||
|
||||
## Features
|
||||
|
||||
- Synchronous and asynchronous clients (`ConduitClient` and `AsyncConduitClient`).
|
||||
- Pydantic v2 request/response models.
|
||||
- Covers every documented Conduit endpoint across gateway, SMS/MMS, media, torrents, wiki, compute, and DNS façades.
|
||||
- Clean error handling with typed exceptions.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install conduit-client
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
```python
|
||||
from conduit_client import ConduitClient
|
||||
|
||||
client = ConduitClient("mega_sk_live_<prefix>_<secret>")
|
||||
me = client.gateway.me()
|
||||
print(me.scopes)
|
||||
```
|
||||
|
||||
## Async usage
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from conduit_client import AsyncConduitClient
|
||||
|
||||
async def main():
|
||||
async with AsyncConduitClient("mega_sk_live_<prefix>_<secret>") as client:
|
||||
me = await client.gateway.me()
|
||||
print(me.scopes)
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
## Per-façade examples
|
||||
|
||||
### Gateway
|
||||
|
||||
```python
|
||||
from conduit_client import ConduitClient
|
||||
from conduit_client.models.common import CreateKeyRequest
|
||||
from conduit_client.models.gateway import AuditLogQuery
|
||||
|
||||
client = ConduitClient("mega_sk_live_<prefix>_<secret>")
|
||||
|
||||
# API keys
|
||||
keys = client.gateway.list_keys()
|
||||
new_key = client.gateway.create_key(CreateKeyRequest(display_name="ci", scopes=["sms:send"]))
|
||||
print(new_key.key) # one-time secret
|
||||
|
||||
# Audit log
|
||||
entries = client.gateway.admin_audit(AuditLogQuery(scope="sms:send", limit=50))
|
||||
```
|
||||
|
||||
### SMS / MMS
|
||||
|
||||
```python
|
||||
from conduit_client.models.sms import SendSmsRequest, SendMmsRequest
|
||||
|
||||
sms_id = client.sms.send_sms(SendSmsRequest(did="5550100", dst="5550200", message="hi"))
|
||||
print(sms_id.id)
|
||||
|
||||
mms_id = client.sms.send_mms(
|
||||
SendMmsRequest(
|
||||
did="5550100",
|
||||
dst="5550200",
|
||||
message="pic",
|
||||
media1="https://example.com/photo.jpg",
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
### Media ingestion (MeTube)
|
||||
|
||||
```python
|
||||
from conduit_client.models.media_ingest import CreateIngestJobRequest
|
||||
|
||||
job = client.media_ingest.create_job(
|
||||
CreateIngestJobRequest(url="https://www.youtube.com/watch?v=abc", quality="best")
|
||||
)
|
||||
print(job.id, job.status)
|
||||
```
|
||||
|
||||
### Media library (Jellyfin)
|
||||
|
||||
```python
|
||||
from conduit_client.models.media_library import LibraryLoginRequest, LibrarySearchQuery
|
||||
|
||||
client.media_library.login(LibraryLoginRequest(username="user", password="pw"))
|
||||
results = client.media_library.search(LibrarySearchQuery(term="Inception"))
|
||||
```
|
||||
|
||||
### Torrents (Transmission)
|
||||
|
||||
```python
|
||||
from conduit_client.models.torrents import AddTorrentRequest
|
||||
|
||||
client.torrents.add(AddTorrentRequest(url="magnet:?xt=urn:btih:...", paused=False))
|
||||
client.torrents.list(fields=["id", "name"])
|
||||
```
|
||||
|
||||
### Wiki (DokuWiki)
|
||||
|
||||
```python
|
||||
from conduit_client.models.wiki import WriteWikiPageRequest
|
||||
|
||||
page = client.wiki.get_raw("namespace:page")
|
||||
client.wiki.write("namespace:page", WriteWikiPageRequest(text="updated content"))
|
||||
```
|
||||
|
||||
### Compute (Proxmox)
|
||||
|
||||
```python
|
||||
from conduit_client.models.compute import CreateVmRequest, ComputeTicketRequest
|
||||
|
||||
ticket = client.compute.auth_ticket(ComputeTicketRequest(username="root", password="pw"))
|
||||
print(ticket.ticket)
|
||||
|
||||
# Create a VM; extra Proxmox fields are forwarded as-is.
|
||||
client.compute.create_vm(
|
||||
CreateVmRequest(node="pve", vmid=100, cores=2, memory=2048, storage="local-lvm")
|
||||
)
|
||||
client.compute.start_vm(100)
|
||||
```
|
||||
|
||||
### DNS (BIND9)
|
||||
|
||||
```python
|
||||
from conduit_client.models.dns import (
|
||||
AddZoneRequest,
|
||||
BatchRecordUpdate,
|
||||
BatchUpdateRecordsRequest,
|
||||
)
|
||||
|
||||
client.dns.create_zone(AddZoneRequest(zone="example.com", klass="IN"))
|
||||
client.dns.batch_update_records(
|
||||
"example.com",
|
||||
BatchUpdateRecordsRequest(
|
||||
updates=[
|
||||
BatchRecordUpdate(op="add", name="www", ttl=300, rtype="A", rdata="1.2.3.4")
|
||||
]
|
||||
),
|
||||
)
|
||||
client.dns.reload_server("default")
|
||||
```
|
||||
|
||||
## Error handling
|
||||
|
||||
```python
|
||||
from conduit_client import ConduitClient, AuthenticationError, NotFoundError
|
||||
|
||||
client = ConduitClient("mega_sk_live_<prefix>_<secret>")
|
||||
|
||||
try:
|
||||
client.sms.delete_sms(999999)
|
||||
except NotFoundError as exc:
|
||||
print(exc.status_code, exc.response_body)
|
||||
except AuthenticationError as exc:
|
||||
print("Invalid API key", exc.status_code)
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
```python
|
||||
from conduit_client import ConduitClient
|
||||
|
||||
client = ConduitClient(
|
||||
"mega_sk_live_<prefix>_<secret>",
|
||||
base_url="https://api.cowtunnel.com",
|
||||
timeout=60.0,
|
||||
max_retries=2,
|
||||
)
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
Reference in New Issue
Block a user