nanoatp
A nano implementation of the AT Protocol for Python.
Demo
- A bot built with nanoatp that summarizes the top 30 most popular arXiv papers on Reddit and Hacker News in the last 30 days and posts them to Bluesky.
Getting started
- First, install the package.
pip install nanoatp
- Set your credentials as environment variables. Or you can pass them to
BskyAgent.login().
export ATP_IDENTIFIER="foo.bsky.social"
export ATP_PASSWORD="password"
- Then in your application,
from nanoatp import BskyAgent, RichText
agent = BskyAgent("https://bsky.social")
agent.login()
# post a simple text
record = {"text": "Hello World!"}
response = agent.post(record)
print(response)
# create a RichText
rt = RichText("Hello @nanoatp.bsky.social, check out this link: https://huggingface.co/")
rt.detectFacets(agent)
print(rt.facets)
# upload an image
image = agent.uploadImage("example.png")
# post a RichText with an image
embed = {"$type": "app.bsky.embed.images", "images": [image]}
record = {"text": rt.text, "facets": rt.facets, "embed": embed}
response = agent.post(record)
print(response)
# upload an external link (create a link card with title, description and thumbnail)
uri = rt.facets[1]["features"][0]["uri"] # https://huggingface.co/
external = agent.uploadExternal(uri)
# post a RichText with an external link
embed = {"$type": "app.bsky.embed.external", "external": external}
record = {"text": rt.text, "facets": rt.facets, "embed": embed}
response = agent.post(record)
print(response)
See examples for more.
Usage
Session management
Log into a server using these APIs. You'll need an active session for most methods.
from nanoatp import BskyAgent
agent = BskyAgent("https://bsky.social")
# if you don't specify credentials,
# ATP_IDENTIFIER and ATP_PASSWORD environment variables will be used
agent.login("alice@mail.com", "hunter2")
API calls
The agent includes methods for many common operations, including:
# Feeds and content
agent.getPost(repo, rkey, cid)
agent.post(record)
agent.deletePost(postUri)
agent.uploadBlob(data, encoding)
agent.uploadImage(path, alt, encoding) # wrapper for uploadBlob
agent.uploadExternal(url) # wrapper for uploadBlob
# Identity
agent.resolveHandle(handle)
# Session management
agent.login(identifier, password)
Rich text
Some records (ie posts) use the app.bsky.richtext lexicon. At the moment richtext is only used for links and mentions, but it will be extended over time to include bold, italic, and so on.
ℹ️ Currently the implementation is very naive. I have not tested it with UTF-16 text.
from nanoatp import BskyAgent, RichText
agent = BskyAgent()
agent.login()
rt = RichText("Hello @nanoatp.bsky.social, check out this link: https://example.com")
rt.detectFacets(agent)
record = {"text": rt.text, "facets": rt.facets}
agent.post(record)
Advanced
Advanced API calls
The methods above are convenience wrappers. It covers most but not all available methods.
The AT Protocol identifies methods and records with reverse-DNS names. You can use them on the agent as well:
res1 = agent._repo_createRecord(
agent.session["did"], # repo
"app.bsky.feed.post", # collection
{
"$type": "app.bsky.feed.post",
"text": "Hello, world!",
"createdAt": datetime.datetime.now(datetime.timezone.utc).isoformat().replace("+00:00", "Z")
}
)
Development
export ATP_IDENTIFIER="foo.bsky.social"
export ATP_PASSWORD="password"
git clone https://github.com/susumuota/nanoatp.git
cd nanoatp
uv sync
source .venv/bin/activate
ptw . -s
TODO:
- split BskyAgent and AtpAgent code
- implement a proper RichText parser with UTF-16 (currently it's very naive)
- type definitions
- structured tests
- more APIs
License
MIT License. See LICENSE for details.
Author
Susumu Ota
Metadata
Release files for nanoatp 0.5.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nanoatp-0.5.1.tar.gz | 8.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nanoatp-0.5.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 17.0 kB
Release files / nanoatp-0.5.1.tar.gz
| Download URL | nanoatp-0.5.1.tar.gz |
|---|---|
| Size | 8.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
00a1ac0f4082bd43e7253b75b3ebd2078709c5e95ed2402bb2bda709f8c0b7c8
|
|
BLAKE2b-256 checksum How to use checksums |
c9ed10794f3f8557687c488625f51dea5025e04c332b75433e513081ca42a33f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.5.31
|
Release files / nanoatp-0.5.1-py3-none-any.whl
| Download URL | nanoatp-0.5.1-py3-none-any.whl |
|---|---|
| Size | 8.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6da67c81d469d1b329f7cc2f710619f1a426840b18f87b7031d0a437b95387bb
|
|
BLAKE2b-256 checksum How to use checksums |
64b87983aafb3df01d63c0dc2b9ff3fbf0787fbbe92496567f169deb1b8edb59
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.5.31
|