Skip to content

Instantly share code, notes, and snippets.

@gskril

gskril/bot.js Secret

Last active October 3, 2022 02:26
Show Gist options
  • Save gskril/59d16fefbc411e61c9cce41963f3accf to your computer and use it in GitHub Desktop.
Save gskril/59d16fefbc411e61c9cce41963f3accf to your computer and use it in GitHub Desktop.
Farcaster bot that responds to mentions (supports V2)
import got from 'got'
import 'dotenv/config'
import cron from 'node-cron'
import { publishCast } from './utils/farcaster.js'
import { Farcaster } from '@standard-crypto/farcaster-js' // version 2.0.2
const lastNotifs = []
const farcaster = new Farcaster()
let firstRun = true
const pKey = process.env.FARCASTER_PRIVATE_KEY
const farcasterAddress = process.env.FARCASTER_ADDRESS
const notificationsApi = `https://api.farcaster.xyz/v1/notifications?address=${farcasterAddress}&per_page=10`
// Check for notifications every 10 seconds
cron.schedule('*/10 * * * * *', async () => {
const res = await got(notificationsApi).then((res) => JSON.parse(res.body))
const notifs = Object.keys(res.result.notifications).map(
(key) => res.result.notifications[key]
)
const newNotifs = notifs.filter(
(notif) =>
!lastNotifs.some((lastNotif) => lastNotif.timestamp === notif.timestamp)
)
lastNotifs.push(...newNotifs)
if (firstRun) {
firstRun = false
console.log(`Watching ${notificationsApi}`)
return
}
const mentions = newNotifs.filter(
(notif) =>
notif.type === 'cast-mention' ||
(notif.type === 'cast-reply' &&
notif.replyCast.text.includes(`@${process.env.USERNAME}`))
)
if (mentions.length === 0) return
// Handle new mentions
for (let i = 0; i < mentions.length; i++) {
const mention = mentions[i]
const user = mention.user.username
const merkleRoot = mention.cast.merkleRoot
let castToReply
// Get the full cast
for await (const activity of farcaster.getAllActivityForUser(user)) {
if (activity.merkleRoot === merkleRoot) {
castToReply = activity
break
}
}
// Reply to the cast
await publishCast(pKey, 'yooooo', castToReply).then(() =>
console.log(`Replied to @${user}`)
)
}
})
import {
Farcaster,
FarcasterGuardianContentHost,
} from '@standard-crypto/farcaster-js'
import { Wallet } from 'ethers'
/**
* MODIFIED FROM STANDARD-CRYPTO LIBRARY
* Signs and publishes a simple text string.
* The cast will be attributed to the username currently registered
* to the given private key's address.
*/
const _defaultFarcaster = new Farcaster()
export async function publishCast(privateKey, text, replyTo) {
const contentHost = new FarcasterGuardianContentHost(privateKey)
const signer = new Wallet(privateKey)
const unsignedCast = await _defaultFarcaster.prepareCast({
fromUsername: process.env.USERNAME,
text,
replyTo,
})
const signedCast = await Farcaster.signCast(unsignedCast, signer)
await contentHost.publishCast(signedCast)
return signedCast
}
import { Wallet } from 'ethers'
/*
Enter your Farcaster mnemonic here to get the private key
associated with your account
*/
getPkeyFromMnemonic('')
function getPkeyFromMnemonic(mnemonic) {
const wallet = Wallet.fromMnemonic(mnemonic)
console.log({
address: wallet.address,
pkey: wallet._signingKey().privateKey,
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment