A serverless bot that generates and posts content using Markov chain text generation across multiple social media platforms (Mastodon, Bluesky). Built using Cloudflare Workers.
- Generates unique social media content using Markov chains
- Configurable parameters for content generation
- Filters out excluded words and phrases
- 30% random posting probability
- Posts to Mastodon
- Posts to Bluesky
- Extensible for additional platforms
- Generates witty, contextual replies using ChatGPT
- Supports both Mastodon and Bluesky post URLs
- Smart reply behavior:
- Always replies to first interaction in a thread
- 30% chance to reply to subsequent interactions
- Skips replies containing excluded words
- Won't reply to posts older than 24 hours
- Avoids replying to its own posts
- Test endpoint for trying replies before posting
- Configurable response style and tone
MASTODON_API_URL
- Your Mastodon instance URLMASTODON_ACCESS_TOKEN
- Mastodon API access tokenBLUESKY_API_URL
- Bluesky API URL (default: https://bsky.social)BLUESKY_USERNAME
- Your Bluesky usernameBLUESKY_PASSWORD
- Your Bluesky app passwordOPENAI_API_KEY
- Your OpenAI API key (required for reply generation)
MASTODON_SOURCE_ACCOUNTS
- Mastodon accounts to source content fromBLUESKY_SOURCE_ACCOUNTS
- Bluesky accounts to source content fromEXCLUDED_WORDS
- Words to exclude from generated content and repliesDEBUG_MODE
- When set to 'true', prevents actual posting and enables detailed loggingDEBUG_LEVEL
- Debug log level (verbose/info/error)MARKOV_STATE_SIZE
- Markov chain state size (default: 2)MARKOV_MIN_CHARS
- Minimum characters in generated post (default: 100)MARKOV_MAX_CHARS
- Maximum characters in generated post (default: 280)MARKOV_MAX_TRIES
- Maximum attempts to generate valid post (default: 100)
The bot includes a comprehensive debug mode that allows you to test functionality without actually posting to social media platforms.
You can enable debug mode in one of three ways:
-
In
.dev.vars
for local development:DEBUG_MODE=true
-
In
wrangler.toml
for development and testing:[vars] DEBUG_MODE = "true"
-
In Cloudflare Dashboard for production:
- Go to Workers & Pages > Your Worker > Settings > Variables
- Add
DEBUG_MODE
with valuetrue
When DEBUG_MODE
is set to 'true':
- No actual posts will be made to any platform
- Detailed logs show what would have been posted
- Reply tracking still works to prevent duplicate debug logs
- All other functionality (notifications, reply generation) works normally
This is useful for:
- Testing reply generation
- Verifying post content before going live
- Debugging notification processing
- Testing rate limit handling
With debug mode enabled, you'll see detailed logs like:
Debug mode: Would post to Bluesky: [post content]
Debug mode: Would reply to Mastodon post: [reply content]
-
Install dependencies:
npm install
-
Create a
.dev.vars
file with your environment variables:MASTODON_API_URL=https://your.mastodon.instance MASTODON_ACCESS_TOKEN=your_token BLUESKY_API_URL=https://bsky.social BLUESKY_USERNAME=your.username BLUESKY_PASSWORD=your_app_password MASTODON_SOURCE_ACCOUNTS=@user@instance BLUESKY_SOURCE_ACCOUNTS[email protected] DEBUG_MODE=true # Start with debug mode enabled for safety DEBUG_LEVEL=verbose OPENAI_API_KEY=your_openai_api_key
-
Start the development server:
wrangler dev
POST /run
- Execute the bot (30% chance to post)POST /upload-tweets
- Upload source contentGET /upload-tweets
- Get source content countPOST /test-reply
- Test AI-powered reply generationPOST /check-replies
- Check for and process new replies
-
Configure your environment variables in Cloudflare:
wrangler secret put MASTODON_ACCESS_TOKEN # Repeat for other secrets
-
Deploy to Cloudflare Workers:
wrangler deploy
- The bot has a 30% chance of posting each time it runs
- When posting, it will attempt to post to both Mastodon and Bluesky
- Generated content is based on source content from specified accounts
- Content is filtered to remove excluded words
- Debug logs show the random percentage and whether a post was attempted
- Written in JavaScript
- Uses Cloudflare Workers for serverless execution
- Stores source content in Cloudflare KV
- Implements Markov chain text generation
- Supports multiple social media platforms
The bot uses the following criteria to determine when to reply:
-
First Interactions
- Always replies to the first interaction in a thread
- Helps establish initial engagement
-
Subsequent Interactions
- 30% chance to reply to follow-up messages
- Prevents excessive back-and-forth conversations
-
Content Filtering
- Skips replies containing words from
EXCLUDED_WORDS
- Won't reply to its own posts
- Ignores posts older than 24 hours
- Skips replies containing words from
-
Debug Mode
- Set
DEBUG_MODE=true
to see detailed decision logging - Helpful for understanding reply behavior
- Set
There are several ways to test the reply functionality:
-
Using the Test Endpoint
# Create test-payload.json with your test data { "postUrl": "https://bsky.app/profile/username.bsky.social/post/postid", "replyContent": "Your test reply content here" } # Test reply generation curl -X POST http://127.0.0.1:8787/test-reply \ -H "Content-Type: application/json" \ --data-binary "@test-payload.json"
-
Testing Live Reply Behavior
# First, make the bot post something curl -X POST http://127.0.0.1:8787/run # Then reply to that post from another account # Finally, trigger reply checking curl -X POST http://127.0.0.1:8787/check-replies
-
Debug Mode Testing
# Enable debug mode in .dev.vars DEBUG_MODE=true DEBUG_LEVEL=verbose # Run the reply checker to see detailed logs curl -X POST http://127.0.0.1:8787/check-replies
-
First Reply Testing
- Post something from the bot
- Reply to it from another account
- Run
/check-replies
- bot should always respond
-
Subsequent Reply Testing
- Continue the conversation
- Run
/check-replies
multiple times - Bot should respond ~30% of the time
-
Content Filter Testing
# Add test words to .dev.vars EXCLUDED_WORDS=test,spam,ignore # Reply to bot with these words # Bot should skip these replies
-
Age Limit Testing
- Reply to an old post (>24h)
- Bot should skip these replies
-
Self-Reply Testing
- Reply to the bot's post using the bot's account
- Bot should skip these replies
-
Check Logs
- Enable verbose logging:
DEBUG_MODE=true DEBUG_LEVEL=verbose
- Look for "Processing notification" and "Reply decision" messages
- Enable verbose logging:
-
Common Issues
- API authentication errors: Check credentials in
.dev.vars
- Missing replies: Verify notification fetching is working
- Unexpected behavior: Check debug logs for decision reasoning
- API authentication errors: Check credentials in
-
Testing Environment
- Use
wrangler dev
for local testing - Create test accounts on both platforms
- Keep test-payload.json in .gitignore
- Use
MIT License - See LICENSE file for details