Easily use Firehose API on Bluesky Social with Dart and Flutter
Shinya Kato
Posted on June 6, 2023
As already noted by many media articles, Bluesky Social is a decentralized social networking service with a Twitter-like UI. Bluesky Social is built on a next-generation common infrastructure called the AT Protocol, and the road ahead is very ambitious and full of unknown possibilities.
Now, I will introduce the Firehose API, one of the APIs related to Bluesky Social, and how to use it easily with the Dart language. Bluesky Social's Firehose API is a very powerful Stream API that allows you to retrieve almost any event occurring on a particular server in real time.
What Is Dart?
For those who are not familiar with the Dart language, Dart is a relatively new programming language developed by Google. Dart has a syntax similar to Java and C, but with modern language specifications such as null safety. Above all, Flutter is probably the reason Dart is getting the most attention.
Flutter transforms the entire app development process. Build, test, and deploy beautiful mobile, web, desktop, and embedded apps from a single codebase.
flutter.dev
Well, there is already a powerful package that makes it easy to use Bluesky Social's API with Dart and Flutter, and this article will present sample code using that package!
Install Package
To easily use Bluesky Social's API in Dart or Flutter, use the package bluesky. I develop and maintain this package and it already supports almost all endpoints, is well tested and very stable.
It is already being used in several third-party apps, and I highly recommend this package for your Bluesky Social-related apps in Dart or Flutter.
Now all that is left is to actually use the Firehose API with the bluesky package! The bluesky package makes it easy to connect to Bluesky Social's Firehose API as follows.
Since the Firehose API used this time does not require user authentication to access it, now we created an instance of the Bluesky object using the .anonymous() constructor, which does not require authentication. The .fromSession() constructor must always be used when using endpoints that require user authentication, but is not used in this article.
The next thing we have to do is to get the Firehose API Stream from an instance of the Bluesky object as follows.
With just this one simple line you can get a Stream of Bluesky Social's Firehose API. This Stream is a long-lived connection and is communicated via WebSocket. But you need not be aware of these difficult communications at all, just write one line above and you will be fine.
Returned from subscribeRepoUpdates() is a subscription data representing the connection to the Firehose API. You can retrieve the data flowing from stream in the following way.
Like above, you can get events that occur in bsky.social from stream. But, the structure of event that can be obtained from this stream is not simple. This event object is of type Union, which simply means that there are multiple structures of objects flowing from the stream.
Do you have to handle those complex structures yourself? No, that is not necessary. The bluesky package provides easy handling of objects of type Union.
Not only in this example, but any object of type Union in the bluesky package can easily handle any structure that may flow as a Union using .when().
For example, using event.when() in the above example, you can safely handle objects with the different structures commit, handle, migrate, tombstone, info and unknown. The unknown is called when there is a Union structure not supported by the bluesky package, and is passed JSON (Map) that is not parsed to a specific object.
But, only the commit and handle patterns are mainly used at this time, and the other structures are not implemented or used in the official Bluesky API. So, let's focus on commit and handle now.
The commit event is fired when a post is posted on Bluesky, or when a specific post is liked and etc. A commit event consists of one or more ops, each op having an action that triggered the event to occur as follows.
For example, in the above case, from op.uri you can get the AT URI of a specific record, and from op.record you can get a specific record according to the AT URI and action.
Next, the handle event is fired when a particular user changes the handle on an account. The handle event is not as difficult as the commit event introduced earlier, you just can get the modified contents of the handle as follows.
I have shown you how to use Bluesky Social's Firehose API using the bluesky package, but there is actually an easier way to handle the commit event. It is to use RepoCommitAdaptor for the commit event as follows.
finalsubscription=awaitbluesky.sync.subscribeRepoUpdates();// Add thisfinalrepoCommit=RepoCommitAdaptor(onCreatePost:(data){print(data.author);print(data.uri);print(data.record);},onUpdateProfile:(data){print(data.record);},onDeleteFollow:(data){print(data.uri);},);awaitfor(finaleventinsubscription.data.stream){event.when(commit:repoCommit.execute,// And execute like thishandle:print,migrate:print,tombstone:print,info:print,unknown:print,);}
You can see at a glance that the RepoCommitAdaptor can be used to process each event in a very concise manner compared to handling each event individually using ops to action, etc., as in the previous example.
The above example specifies onCreatePost, onUpdateProfile, and onDeleteFollow when creating an instance of RepoCommitAdaptor, which means that only the following events can be filtered and retrieved.
onCreatePost: When the Post is created.
onUpdateProfile: When the Profile is updated.
onDeleteFollow: When the Follow is deleted.
Of course, the above examples are only some of the events supported by RepoCommitAdaptor.
The RepoCommitAdaptor provides very powerful and secure handling when using Bluesky Social's Firehose API with the bluesky package. When using subscribeRepoUpdates() to handle commit events, it would be best to use the RepoCommitAdaptor.
Conclusion
This is how to easily use Bluesky Social's Firehose API with Dart and Flutter using the bluesky package.
This article is basically an example with a Dart program, but the bluesky package also works with Flutter, so similar code can be used to make the Firehose API work in a Flutter app. You can use the StreamBuilder widget when working with Firehose API Streams in Flutter.
As mentioned earlier, the bluesky package also supports many endpoints other than the Firehose API presented here. This is a very powerful package that will surely be useful in the Dart/Flutter apps you develop!
In addition to the bluesky package I have presented here, I have also developed many AT Protocol related packages for Dart/Flutter in the following monorepo. If you are interested in AT Protocol related packages for Dart/Flutter, please check it out!
This wonderful platform needs a standard and highly integrated SDK
atproto.dart provides the best development experience in such matters for Dart/Flutter devs.
2. Packages & Tools āļø
2.1. Dart Packages
Package
pub.dev
Docs
at_identifier: core library for the syntax in the AT Protocol standard