-
-
Save gskril/59d16fefbc411e61c9cce41963f3accf to your computer and use it in GitHub Desktop.
Farcaster bot that responds to mentions (supports V2)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}`) | |
) | |
} | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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