Logo

dev-resources.site

for different kinds of informations.

How to Create Bluesky BOT using Dart and Firehose

Published at
9/9/2023
Categories
dart
bluesky
atproto
bot
Author
shinyakato
Categories
4 categories in total
dart
open
bluesky
open
atproto
open
bot
open
Author
10 person written this
shinyakato
open
How to Create Bluesky BOT using Dart and Firehose

This article shows how to create a BOT with real-time data using the Dart language and Bluesky's Firehose API.

From the Firehose API, you can retrieve Bluesky events that occur on a particular server in real time, allowing you to develop very interactive BOTs. For example, a reply can be returned in real time to data that has been mentions to a specific account.

After reading this article you will surely be able to create a BOT using the Firehose API.

BOTs intended to spam will be subject to account suspension.
I will not be liable for any account suspension as a result of spamming or otherwise. Please execute with care when testing.

Using Package

To easily handle the Bluesky API in Dart/Flutter, use the following package.

bluesky | Dart package

The most famous and powerful Dart/Flutter library for Bluesky Social.

favicon pub.dev

GitHub logo myConsciousness / atproto.dart

šŸ¦‹ AT Protocol and Bluesky things for Dart and Flutter.

bluesky

AT Protocol and Bluesky Social Things for Dart/Flutter šŸ¦‹


GitHub Sponsor GitHub Sponsor melos Reference

Test/Analyzer codecov Issues Pull Requests Stars Contributors Code size Last Commits License Contributor Covenant


Welcome to atproto.dart šŸ¦‹

This project will maximize your development productivity about AT Protocol and Bluesky things.

Give a ā­ on GitHub repository and follow shinyakato.dev on Bluesky!

1. Motivation šŸ’Ŗ

AT Protocol and Bluesky are awesome.

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 pub package README
nsid:
ā€¦

If you want to learn more about bluesky package, see following official website.

AT Protocol and Bluesky Social Things for Dart and Flutter | atproto.dart

Powerful suite of AT Protocol and Bluesky-related packages for Dart/Flutter

favicon atprotodart.com

Install

Let's install bluesky with the following commands.

dart pub add bluesky
Enter fullscreen mode Exit fullscreen mode
dart pub get
Enter fullscreen mode Exit fullscreen mode

Import

Basically, when you use features of the bluesky package, just add the following import.

import 'package:bluesky/bluesky.dart';
Enter fullscreen mode Exit fullscreen mode

Basic

Let's begin with the most basic implementation for using the Firehose API with bluesky package. You can implement it as follows.

import 'package:bluesky/bluesky.dart' as bsky;

Future<void> main() async {
  final bluesky = bsky.Bluesky.anonymous();

  final subscription = await bluesky.sync.subscribeRepoUpdates();

  await for (final event in subscription.data.stream.handleError(print)) {
    print(event);
  }
}
Enter fullscreen mode Exit fullscreen mode

To start with the most basic point, almost all events (likes and postings and etc) that occur on a particular server in Bluesky are public data. In other words, the Firehose API does not require user authentication.

With the above code, Bluesky's Firehose works perfectly, but user authentication is always required with a specific account to develop a BOT like the one we will cover in this article. This is because the BOT must be logged in with a specific account in order to respond with a reply or other action when a specific event is detected.

So, we need following implementations.

import 'package:bluesky/bluesky.dart' as bsky;

Future<void> main() async {
  //  This session is active for 120 minutes.
  final session = await bsky.createSession(
    identifier: 'username or email',
    password: 'password',
  );

  // Refreshed session is active for 90 days.
  final refreshedSession = await bsky.refreshSession(
    refreshJwt: session.data.refreshJwt,
  );

  // Create an instance from authenticated session.
  final bluesky = bsky.Bluesky.fromSession(refreshedSession.data);

  final subscription = await bluesky.sync.subscribeRepoUpdates();

  await for (final event in subscription.data.stream.handleError(print)) {
    print(event);
  }
}
Enter fullscreen mode Exit fullscreen mode

Comparing with the previous code, you will notice that the .createSession function adds a process to authenticate the user. By passing username and password credentials to the .createSession function, a Bluesky session is created and you are logged in with a specific account.

But it's important to note, however, that sessions created with the .createSession function are only valid for 120 minutes. This is a somewhat unreliable time limit when using the Firehose API for long-time connections.

So, let's use the .refreshSession function. By passing refreshJwt in the session object created by the .createSession function as an argument, you can issue a session that is valid for 90 days.

Advanced

Move on to the main issue!

Let's create a BOT that replies with Hello! if it detects a post "Say hello @test.shinyakato.dev".

import 'package:bluesky/bluesky.dart' as bsky;

Future<void> main() async {
  //  This session is active for 120 minutes.
  final session = await bsky.createSession(
    identifier: 'username or email',
    password: 'password',
  );

  // Refreshed session is active for 90 days.
  final refreshedSession = await bsky.refreshSession(
    refreshJwt: session.data.refreshJwt,
  );

  // Create an instance from authenticated session.
  final bluesky = bsky.Bluesky.fromSession(refreshedSession.data);

  final subscription = await bluesky.sync.subscribeRepoUpdates();

  // This is a very useful adaptor.
  // You can filter only specific events from Firehose.
  final adaptor = bsky.RepoCommitAdaptor(
    // Triggered only when post is created.
    onCreatePost: (data) async {
      if (data.record.text.contains('Say hello @test.shinyakato.dev')) {
        // Post a reply
        await bluesky.feeds.createPost(
          text: 'Hello!',

          // Reply setting
          reply: bsky.ReplyRef(
            root: data.toStrongRef(),
            parent: data.toStrongRef(),
          ),
        );

        print('said hello to ${data.author}!');
      }
    },
  );

  await for (final event in subscription.data.stream.handleError(print)) {
    switch (event) {
      // Firehose events are union type.
      // Use `USubscribedRepoCommit` to filter only commit events.
      case bsky.USubscribedRepoCommit():
        // Execute adaptor like this.
        await adaptor.execute(event.data);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Well done, if you run this code and post "Say hello @test.shinyakato.dev", you will instantly receive a reply saying "Hello!".

"Oh no, this seems very difficult to implement!"

Don't worry. The implementation has increased but it's very simple.

First, I describe the RepoCommitAdaptor class. The RepoCommitAdaptor class is a solution that allows troublesome commit data records to be filtered and treated as a specific type.

The commit data returned from Firehose contains almost all the record data generated by Bluesky. This means that the implementer must check as to whether the content of the record is a post or a like and so on. But, this is a fairly burdensome task for implementors using Firehose... Well, let RepoCommitAdaptor take care of all that tedious work.

When using RepoCommitAdaptor, you can define processing directly in callbacks for specific events such as onCreatePost as follows.

  // This is a very useful adaptor.
  // You can filter only specific events from Firehose.
  final adaptor = bsky.RepoCommitAdaptor(
    // Triggered only when post is created.
    onCreatePost: (data) {
      // Do something for post data.
    },
  );
Enter fullscreen mode Exit fullscreen mode

In other words, this callback is executed only for events for which a post was created upon receipt of the Firehose results.

The code for Firehose is then as follows.

  await for (final event in subscription.data.stream.handleError(print)) {
    switch (event) {
      // Firehose events are union type.
      // Use `USubscribedRepoCommit` to filter only commit events.
      case bsky.USubscribedRepoCommit():
        // Execute adaptor like this.
        await adaptor.execute(event.data);
    }
  }
Enter fullscreen mode Exit fullscreen mode

As noted in the comments to the above code, the data returned from Firehose is union. But, it can be easily handled using pattern matching in Dart3.

Union type names in bluesky package is always prefixed with U, so in this case we specify the USubscribedRepoCommit class in case, which represents Firehose's repo commit event.

Finally, the RepoCommitAdaptor defined earlier is executed in a case statement. This will all be easily resolved.

Conclusion

After reading this article you now understand how to use Dart and Bluesky's Firehose to create a realtime oriented BOT. Although we created a very simple BOT in this article, it's possible to create a more serviceable BOT by incorporating more complex rules. Try various things with the bluesky package!

If you are still not sure how to implement it after reading this article, please mention me on Bluesky.

Also, if you found this article useful, please give a star on GitHub repository. This is very helpful to activate the development community for atproto.dart.

GitHub logo myConsciousness / atproto.dart

šŸ¦‹ AT Protocol and Bluesky things for Dart and Flutter.

bluesky

AT Protocol and Bluesky Social Things for Dart/Flutter šŸ¦‹


GitHub Sponsor GitHub Sponsor melos Reference

Test/Analyzer codecov Issues Pull Requests Stars Contributors Code size Last Commits License Contributor Covenant


Welcome to atproto.dart šŸ¦‹

This project will maximize your development productivity about AT Protocol and Bluesky things.

Give a ā­ on GitHub repository and follow shinyakato.dev on Bluesky!

1. Motivation šŸ’Ŗ

AT Protocol and Bluesky are awesome.

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 pub package README
nsid:
ā€¦

Thank you.

bluesky Article's
30 articles in total
Favicon
How I Built a Profitable Bluesky Tool Directory in 7 Days
Favicon
I feel like Elon killed Twitter and I plan to be more "developerly active " on BlueSky! https://bsky.app/profile/mahanaz.bsky.social But I want to get back to posting, sharing, and connecting, so that's why I'm here! :)
Favicon
How to add comment from BlueSky to static/vue/nuxt project
Favicon
How to Build a GenAI Bluesky Bot with Langflow, TypeScript, and Node.js
Favicon
āœļø Cross-Posting Astro Blog Posts to BlueSky Using GPT-4 šŸ§ 
Favicon
How decentralized is Bluesky really?
Favicon
Thoughts on bluesky Vs X for technical discussions?
Favicon
How to use GitHub to be verified on Bluesky
Favicon
How to post a link with embed card on Bluesky with JavaScript
Favicon
Fetching Liked Posts Using the Bluesky API
Favicon
Free Insights for any Bluesky šŸ¦‹ profile
Favicon
Custom Bluesky Handle on AWS with Terraform/OpenTofu
Favicon
How to Build a BlueSky RSS-like Bot with AWS Lambda and Terraform
Favicon
Skymood - Watch Bluesky's heartbeat through emojis in real-time šŸŒŸ
Favicon
The Journey of CDK.dev: From Static Site to Bluesky
Favicon
AT Protocol services
Favicon
Building my own Zero Dawn platform
Favicon
Creating a Bot for Bluesky Social
Favicon
How Web5 and Bluesky are Building the Next Layer of the Web - A Comparative Analysis
Favicon
So, you want to publish in Bluesky with a python program?
Favicon
Posting on Bluesky Social using Python in 1 minute
Favicon
How to Create Bluesky BOT using Dart and Firehose
Favicon
How to Update Your Profile from Dart/Flutter App using Bluesky API
Favicon
A nova rede social Bluesky
Favicon
Let's Post to Bluesky Social easily with Dart and Flutter
Favicon
Easily use Firehose API on Bluesky Social with Dart and Flutter
Favicon
Bringing custom domains back to Glitch and bots to Bluesky šŸ¤–šŸŒ¤ļø
Favicon
Build bots on Bluesky with Node.js and GitHub Actions
Favicon
What is Bluesky Social Network? And why are developers excited about it?
Favicon
We're on Bluesky ā˜ļø

Featured ones: