Skip to main content

Core functionality of bovine needed to build client to server applications

Project description

Bovine

This package contains two essential parts of bovine. First it defines BovineActor, which contains all the necessities to write ActivityPub Clients. Furthermore, this package contains the cryptographic routines to verify HTTP signatures.

Furthermore, the folder examples contains a few examples on how BovineActor can be used. The cryptographic routines are used in bovine_fedi to verify signatures.

Example: Make a post aka Faking at being a Server

While ActivityPub specifies Server to Server and Client to Server, they really are just two sides of the same coin. In this example, we will work through how to use BovineActor to post a message.

Without having an ActivityPub Server supporting Client to Server, this will require a bit of setup. This setup will build a stub server that just allows other ActivityPub servers to associate us with a domain.

FIXME!!!

Stuff needed:

  • Generate Keys
  • Webfinger
  • Actor object
  • How to deploy
  • How to post

Using BovineActor

One can import it via from bovine import BovineActor. Then one can either use it via:

async with BovineActor(config) as actor:
    ...
# or
actor = BovineActor(config)
await actor.init()

Here the config object can be present in two variants. First it can contain the keys host and private_key, where host is the domain the ActivityPub Actor is on and private_key is a mutlicodec encoded Ed25519 key, whose corresponding did-key has been added to the Actor. In this case Moo-Auth-1 will be used. The second variant is to use HTTP Signatures, where the keys account_url, public_key_url, and private_key need to be present. Alternatively, to passing a config object, one can use BovineActor.from_file(path_to_toml_file).

Making a post

BovineActor contains two factories to create ActivityStreams Objects and ActivityStreams Activities. One can obtain them by running

activity_factory, object_factory = actor.factories

The simplest usage example is a create wrapping a note, that looks like:

activity_factory, object_factory = actor.factories
note = object_factory.note("Hello").as_public().build()
create = activity_factory.create(note).build()

The result should be the something equivalent to the json

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Create",
  "actor": "https://domain/actor",
  "object": {
    "attributedTo": "https://domain/actor",
    "type": "Note",
    "content": "Hello",
    "published": "2023-03-25T08:12:32Z",
    "to": "as:Public",
    "cc": "https://domain/followers_collection"
  },
  "published": "2023-03-25T08:12:32Z",
  "to": "as:Public",
  "cc": "https://domain/followers_collection"
}

The details depend on the used actor and will likely contain superfluous elements until the creation process is improved. We can now send this activity to our outbox using

await actor.send_to_outbox(create)

Note: This is different from what we did in the first example, where we used await actor.post(inbox, create). The difference is that in the first example, we faked being a server, now we are actually using Client To Server.

The inbox and outbox

By running

inbox = await actor.inbox()
outbox = await actor.outbox()

one can obtain CollectionHelper objects. These are meant to make it easier to interact with collection objects. In the simplest use case, one can use

await inbox.next_item()

to get the items from the inbox one after the other. It is also possible to print a summary of all elements that have been fetched from the inbox using await inbox.summary(). Finally, it is possible to iterate over the inbox via

async for item in inbox.iterate(max_number=3):
    do_something(item)

Proxying elements

We have already seen the difference between using post directly to an inbox and posting to the actor's outbox using send_to_outbox. A similar pattern applies to fetching objects. Both of these commands often have a similar result

await actor.get(object_id)
await actor.proxy_element(object_id)

However, they do different things:

  • The first actor.get sends a webrequest to the server object_id is on and retrieves it
  • The second actor.proxy_element sends a request to the actor's server for the object. This request is then either answered from the server's object store or by the server fetching the object. The cache behavior is up to the server. Depending of the evolution of proxyUrl of an Actor, more options might be added here.

As most servers don't support Moo-Auth-1, using proxy_element is the only way to obtain foreign objects, when using it.

Event Source

The event source is demonstrated in examples/sse.py. First, the event source will be specified in a FEP to come. It provides a way to receive updates from the server, whenever a new element is added to the inbox or outbox. The basic usage is

event_source = await actor.event_source()
async for event in event_source:
    if event and event.data:
        data = json.loads(event.data)
        do_something(data)

If you plan on writing long running applications, the event source does not automatically reconnect, so you will need to implement this. mechanical_bull uses the event source in this way.

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

bovine-0.0.8.tar.gz (26.6 kB view details)

Uploaded Source

Built Distribution

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

bovine-0.0.8-py3-none-any.whl (42.5 kB view details)

Uploaded Python 3

File details

Details for the file bovine-0.0.8.tar.gz.

File metadata

  • Download URL: bovine-0.0.8.tar.gz
  • Upload date:
  • Size: 26.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.3.2 CPython/3.10.6 Linux/5.15.0-67-generic

File hashes

Hashes for bovine-0.0.8.tar.gz
Algorithm Hash digest
SHA256 efd01402fdd6e93eb57f409ec558c3d74f585fd0888a1c156aee4499c3284359
MD5 84803798a24a29187c86a094a68e61f5
BLAKE2b-256 bfbbb28d84e740fe666112608757c16130879020112a0fbe0430d4784ecb7330

See more details on using hashes here.

File details

Details for the file bovine-0.0.8-py3-none-any.whl.

File metadata

  • Download URL: bovine-0.0.8-py3-none-any.whl
  • Upload date:
  • Size: 42.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.3.2 CPython/3.10.6 Linux/5.15.0-67-generic

File hashes

Hashes for bovine-0.0.8-py3-none-any.whl
Algorithm Hash digest
SHA256 426d92f05530dffc26a0570db15f1f426a44a9ce0bfc37581287e4362e969098
MD5 48ce10fa4d06d21c8c3200fb932c8ba4
BLAKE2b-256 cc7578f3517c0b207ac736265aee97f30ed5ef64a88f2cb54ddd0562e7eb153e

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