Skip to main content

Python client library for Spot messaging protocol

Project description

pyspotlib

Python client library for the Spot messaging protocol. This is a port of spotlib (Go) to Python.

Features

  • Connect to Spot servers via WebSocket
  • End-to-end encrypted messaging using pybottle
  • Query/response pattern for RPC-style communication
  • Encrypted blob storage
  • ID card caching for efficient encryption
  • Automatic connection management and reconnection

Installation

pip install pyspotlib

Or install from source:

git clone https://github.com/KarpelesLab/pyspotlib.git
cd pyspotlib
pip install -e .

Quick Start

import asyncio
from pyspotlib import new_client

async def main():
    # Create and connect a client
    client = await new_client()
    await client.wait_online()

    print(f"Connected! Target ID: {client.target_id}")

    # Get server time
    server_time = await client.get_time()
    print(f"Server time: {server_time}")

    # Store and retrieve encrypted data
    await client.store_blob("my_key", b"secret data")
    data = await client.fetch_blob("my_key")

    await client.close()

asyncio.run(main())

API Reference

Creating a Client

from pyspotlib import new_client, Client, DiskStore

# Simple ephemeral client (generates new key each time)
client = await new_client()

# Client with persistent key storage
store = DiskStore("/path/to/keys")
client = await new_client(store=store)

# Client without auto-start
client = Client()
await client.start()

Client Properties

  • client.target_id - The client's address in k.<hash> format
  • client.idcard - The client's identity card
  • client.idcard_bin - The client's signed identity card as bytes

Querying Endpoints

# Query a system endpoint
result = await client.query("@/time", b"")

# Query another client's endpoint
result = await client.query("k.<hash>/endpoint", payload)

# With custom timeout
result = await client.query("@/time", b"", timeout=60.0)

Sending Messages

# Send without waiting for response
await client.send_to("k.<hash>/endpoint", payload)

# With custom sender address
await client.send_to("k.<hash>/endpoint", payload, sender="/my-sender")

Blob Storage

# Store encrypted blob (only you can decrypt it)
await client.store_blob("key", b"data")

# Fetch blob
data = await client.fetch_blob("key")

# Delete blob
await client.store_blob("key", b"")

Message Handlers

# Set a handler for incoming messages
async def my_handler(msg):
    # Process message
    return response_bytes, None  # (response, error)

client.set_handler("my_endpoint", my_handler)

# Remove handler
client.set_handler("my_endpoint", None)

Built-in Handlers

The client automatically responds to these endpoints:

  • ping - Echo back the message (up to 128 bytes)
  • version - Return library version info
  • finger - Return the client's signed ID card
  • check_update - Logs update check request
  • idcard_update - Updates ID card cache from server notifications

PacketConn (Packet-based Messaging)

For easy packet-based communication:

# Create a packet connection
conn = client.listen_packet("my_endpoint")

# Receive packets
data, addr = await conn.read_from(timeout=10.0)
print(f"Received {len(data)} bytes from {addr}")

# Send packets
await conn.write_to(b"response data", addr)

# Get local address
print(f"Listening on: {conn.local_addr()}")

# Clean up
await conn.close()

Utility Methods

# Get server time
time = await client.get_time()

# Get ID card for a recipient
idcard = await client.get_idcard(hash_bytes)
idcard = await client.get_idcard_for_recipient("k.<hash>/endpoint")

# Get raw ID card bytes
idcard_bytes = await client.get_idcard_bin(hash_bytes)

# Get group members
members = await client.get_group_members(group_key_bytes)

# Check connection status
total, online = client.connection_count()

# Wait for connection
connected = await client.wait_online(timeout=30.0)

# Query with explicit timeout (alternative syntax)
result = await client.query_timeout(30.0, "@/time", b"")

Address Formats

Format Description
k.<hash> Key-based address (SHA-256 hash of public key, base64url)
k.<hash>/endpoint Key-based with endpoint
@/endpoint System endpoint

Protocol

pyspotlib implements the Spot protocol as defined in spotproto. Messages are encrypted end-to-end using the Bottle format from pybottle.

Message Flags

  • MsgFlagResponse (0x01) - Response message
  • MsgFlagError (0x02) - Error response
  • MsgFlagNotBottle (0x04) - Unencrypted body

Dependencies

  • pybottle >= 0.1.1 - Cryptographic message containers
  • websockets >= 12.0 - WebSocket client
  • cbor2 >= 5.6.0 - CBOR encoding
  • httpx >= 0.27.0 - HTTP client

License

MIT License - see LICENSE file for details.

Related Projects

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyspotlib-0.1.0.tar.gz (19.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyspotlib-0.1.0-py3-none-any.whl (20.0 kB view details)

Uploaded Python 3

File details

Details for the file pyspotlib-0.1.0.tar.gz.

File metadata

  • Download URL: pyspotlib-0.1.0.tar.gz
  • Upload date:
  • Size: 19.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for pyspotlib-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1e982b839774fe82f071565039f8c55633d742e29fa8f9f531d5ae81f494284b
MD5 9843c22bed20a0aa3caf048a0ae5cc16
BLAKE2b-256 1329fb6a9283071c8ed4e39eb3fff30f7c8bbaa3874d4f3de354125855415ab3

See more details on using hashes here.

File details

Details for the file pyspotlib-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pyspotlib-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 20.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for pyspotlib-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 12ac3c2c8eca3efdbf74a78ef16eb13f9f8dc101b9234b940c66d6c83c8b8478
MD5 a6d08ccc8adae1b7102ad3340f4b3524
BLAKE2b-256 1f4d3acf9196af85e90fe0cbb1e6c35618ed344c1146d755dfa49349bb751492

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page