Bluesky GPT: Respond to Bluesky Posts with OpenAI

This is a sample app showing you how to create Bluesky apps
with Autocode and OpenAI. It has two main functions;
- Generate a new post for your main feed every 1h on the :45 mark
- Reply to new @mentions by liking and responding to the post
You can install it and get it working immediately by following
the installation instructions on this page: you'll only have to link your
OpenAI API key and Bluesky API key, which Autocode will help you generate.
You can then edit the code and get a fully-functional GPT-powered Bluesky bot!
If you haven't used Autocode before, it's an online IDE and
serverless hosting platform for Node.js apps that comes with a library of 3rd
party APIs baked in to a Standard Library. For example, sending a post to
Bluesky on Autocode is as simple as;
// Create a post
let post = await lib.bluesky.feed['@0.1.0'].posts.create({
content: 'This is my post!'
});
How does this work?
There are two files, functions/events/scheduler/hourly.js
which created a new
GPT-written Bluesky posts every hour on the :45 mark. It's less than 50 lines
of code.
All API credentials are managed via your STDLIB_SECRET_TOKEN
which will get
automatically generated when you fork the project and link your API credentials.
// authenticates you with the API standard library
// type `await lib.` to display API autocomplete
const lib = require('lib')({token: process.env.STDLIB_SECRET_TOKEN});
// Set up chatML messages for OpenAI completion
let chatML = [
{
role: 'system',
content: [
'- You are a bot on a new social network, Bluesky',
'- Your job is to create positive, uplifting content',
].join('\n')
},
{
role: 'user',
content: [
`- Your job is to create engaging content`,
`- You do this by writing posts that get people to engage`,
`- The social network you're posting to is called Bluesky`,
`- Bluesky is similar to Twitter but brand new`,
`- You can get people to engage by asking questions about themselves`,
`- Or just generally share insightful, uplifting posts`,
`- Write a post that helps get engagement`,
`- Your post should be 280 characters or less, ideally shorter`,
`- Use a jovial tone, informal, no need to capitalize everything`,
`- Emojis can help when used sparingly`,
``,
`Your post:`
].join('\n')
}
];
// Create completion
let completion = await lib.openai.playground['@0.2.1'].chat.completions.create({
model: `gpt-3.5-turbo`,
messages: chatML,
max_tokens: 128,
temperature: 1,
top_p: 1,
n: 1,
presence_penalty: 0,
frequency_penalty: 0
});
let result = completion.choices[0].message.content;
// Create a post
let post = await lib.bluesky.feed['@0.1.0'].posts.create({
content: result
});
return post;
The other file is a little bit more complex, functions/events/scheduler/minutely.js
.
Once a minute this file will execute and check through mentions, looking for new ones.
If it finds one, it will write a response to the post mentioning the bot. The
reply coordination is similar to the above but we use the utils.kv
API to
store the last notification URI you responded to.
Notification tracking is done via the following code;
// authenticates you with the API standard library
// type `await lib.` to display API autocomplete
const lib = require('lib')({token: process.env.STDLIB_SECRET_TOKEN});
const LAST_NOTIFICATION_KEY = `bluesky-gpt:last-notification`;
// Get the notifications and lastNotificationURI
// We save this in a key-value store so we only respond to new notifs
let [
notificationsResult,
lastNotificationURI
] = await Promise.all([
lib.bluesky.feed['@0.1.0'].notifications.list({limit: 100}),
lib.utils.kv['@0.1.16'].get({key: LAST_NOTIFICATION_KEY})
]);
// Update the last notification Key
let notifications = notificationsResult.notifications;
if (notifications.length && lastNotificationURI !== notifications[0].uri) {
await lib.utils.kv['@0.1.16'].set({
key: LAST_NOTIFICATION_KEY,
value: notifications[0].uri
});
}
And likes / replies are handled a little differently:
// Like the post
await lib.bluesky.feed['@0.1.0'].likes.create({
postUri: postUri
});
// Reply to post
let reply = await lib.bluesky.feed['@0.1.0'].posts.create({
content: result,
replyUri: postUri
});
Acknowledgements
Thanks to the Bluesky team for creating such a flexible API!
If you'd like to learn more about Autocode, join us on Discord at
discord.gg/autocode.