Package: nanoatp
nanoatpEN |JA|ES|ZHA nano implementation of the AT Protocol for Python.DemoA 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.@paper.bsky.socialIt needs to have an account on Bluesky to see the posts. But there is a similar bot on Twitter@susumuota.Source codeGetting startedFirst, install the package.pipinstallnanoatpSet your credentials as environment variables. Or you can pass them toBskyAgent.login().exportATP_IDENTIFIER="foo.bsky.social"exportATP_PASSWORD="password"Then in your application,fromnanoatpimportBskyAgent,RichTextagent=BskyAgent("https://bsky.social")agent.login()# post a simple textrecord={"text":"Hello World!"}response=agent.post(record)print(response)# create a RichTextrt=RichText("Hello @nanoatp.bsky.social, check out this link: https://huggingface.co/")rt.detectFacets(agent)print(rt.facets)# upload an imageimage=agent.uploadImage("example.png")# post a RichText with an imageembed={"$type":"app.bsky.embed.images#main","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 linkembed={"$type":"app.bsky.embed.external#main","external":external}record={"text":rt.text,"facets":rt.facets,"embed":embed}response=agent.post(record)print(response)Seeexamplesfor more.UsageSession managementLog into a server using these APIs. You'll need an active session for most methods.fromnanoatpimportBskyAgentagent=BskyAgent("https://bsky.social")# if you don't specify credentials,# ATP_IDENTIFIER and ATP_PASSWORD environment variables will be usedagent.login("alice@mail.com","hunter2")API callsThe agent includes methods for many common operations, including:# Feeds and contentagent.getPost(repo,rkey,cid)agent.post(record)agent.deletePost(postUri)agent.uploadBlob(data,encoding)agent.uploadImage(path,alt,encoding)# wrapper for uploadBlobagent.uploadExternal(url)# wrapper for uploadBlob# Identityagent.resolveHandle(handle)# Session managementagent.login(identifier,password)Rich textSome records (ie posts) use theapp.bsky.richtextlexicon. 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.fromnanoatpimportBskyAgent,RichTextagent=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)AdvancedAdvanced API callsThe 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")})DevelopmentexportATP_IDENTIFIER="foo.bsky.social"exportATP_PASSWORD="password"poetryinstall
poetryrunpytest-s# run pytest oncepoetryrun--ptw---s# watch for changes and run pytestTODO:split BskyAgent and AtpAgent codeimplement a proper RichText parser with UTF-16 (currently it's very naive)type definitionsstructured testsmore APIsLicenseMIT License. SeeLICENSEfor details.AuthorS. Ota