{"id":21976612,"url":"https://github.com/jerdog/serverless-social-bot","last_synced_at":"2026-02-13T04:17:04.753Z","repository":{"id":264946771,"uuid":"894738863","full_name":"jerdog/serverless-social-bot","owner":"jerdog","description":"A Node.js-based bot that generates and posts content to 🐘 and 🦋 using Markov chains.","archived":false,"fork":false,"pushed_at":"2024-12-07T20:51:34.000Z","size":277,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-05T05:06:49.396Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jerdog.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-26T22:38:29.000Z","updated_at":"2024-12-06T05:15:49.000Z","dependencies_parsed_at":"2024-11-26T23:37:04.006Z","dependency_job_id":null,"html_url":"https://github.com/jerdog/serverless-social-bot","commit_stats":null,"previous_names":["jerdog/serverless-social-bot"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jerdog%2Fserverless-social-bot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jerdog%2Fserverless-social-bot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jerdog%2Fserverless-social-bot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jerdog%2Fserverless-social-bot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jerdog","download_url":"https://codeload.github.com/jerdog/serverless-social-bot/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235959116,"owners_count":19072579,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-29T16:11:20.734Z","updated_at":"2025-10-10T13:32:12.080Z","avatar_url":"https://github.com/jerdog.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Serverless Social Media Markov Bot\n\nA serverless bot that generates and posts content using Markov chain text generation across multiple social media platforms (Mastodon, Bluesky). Built using Cloudflare Workers.\n\n## Features\n\n### Content Generation\n- Generates unique social media content using Markov chains\n- Configurable parameters for content generation\n- Filters out excluded words and phrases\n- 30% random posting probability\n\n### Multi-Platform Support\n- Posts to Mastodon\n- Posts to Bluesky\n- Extensible for additional platforms\n\n### AI-Powered Reply Generation\n- Generates witty, contextual replies using ChatGPT\n- Supports both Mastodon and Bluesky post URLs\n- Smart reply behavior:\n  - Always replies to first interaction in a thread\n  - 30% chance to reply to subsequent interactions\n  - Skips replies containing excluded words\n  - Won't reply to posts older than 24 hours\n  - Avoids replying to its own posts\n- Test endpoint for trying replies before posting\n- Configurable response style and tone\n\n## Configuration\n\n### Required Environment Variables\n\n- `MASTODON_API_URL` - Your Mastodon instance URL\n- `MASTODON_ACCESS_TOKEN` - Mastodon API access token\n- `BLUESKY_API_URL` - Bluesky API URL (default: https://bsky.social)\n- `BLUESKY_USERNAME` - Your Bluesky username\n- `BLUESKY_PASSWORD` - Your Bluesky app password\n- `OPENAI_API_KEY` - Your OpenAI API key (required for reply generation)\n\n### Optional Environment Variables\n\n- `MASTODON_SOURCE_ACCOUNTS` - Mastodon accounts to source content from\n- `BLUESKY_SOURCE_ACCOUNTS` - Bluesky accounts to source content from\n- `EXCLUDED_WORDS` - Words to exclude from generated content and replies\n- `DEBUG_MODE` - When set to 'true', prevents actual posting and enables detailed logging\n- `DEBUG_LEVEL` - Debug log level (verbose/info/error)\n- `MARKOV_STATE_SIZE` - Markov chain state size (default: 2)\n- `MARKOV_MIN_CHARS` - Minimum characters in generated post (default: 100)\n- `MARKOV_MAX_CHARS` - Maximum characters in generated post (default: 280)\n- `MARKOV_MAX_TRIES` - Maximum attempts to generate valid post (default: 100)\n\n## Debug Mode\n\nThe bot includes a comprehensive debug mode that allows you to test functionality without actually posting to social media platforms.\n\n### Enabling Debug Mode\n\nYou can enable debug mode in one of three ways:\n\n1. In `.dev.vars` for local development:\n   ```ini\n   DEBUG_MODE=true\n   ```\n\n2. In `wrangler.toml` for development and testing:\n   ```toml\n   [vars]\n   DEBUG_MODE = \"true\"\n   ```\n\n3. In Cloudflare Dashboard for production:\n   - Go to Workers \u0026 Pages \u003e Your Worker \u003e Settings \u003e Variables\n   - Add `DEBUG_MODE` with value `true`\n\n### What Debug Mode Does\n\nWhen `DEBUG_MODE` is set to 'true':\n- No actual posts will be made to any platform\n- Detailed logs show what would have been posted\n- Reply tracking still works to prevent duplicate debug logs\n- All other functionality (notifications, reply generation) works normally\n\nThis is useful for:\n- Testing reply generation\n- Verifying post content before going live\n- Debugging notification processing\n- Testing rate limit handling\n\n### Debug Logs\n\nWith debug mode enabled, you'll see detailed logs like:\n```\nDebug mode: Would post to Bluesky: [post content]\nDebug mode: Would reply to Mastodon post: [reply content]\n```\n\n## Local Development\n\n1. Install dependencies:\n   ```bash\n   npm install\n   ```\n\n2. Create a `.dev.vars` file with your environment variables:\n   ```ini\n   MASTODON_API_URL=https://your.mastodon.instance\n   MASTODON_ACCESS_TOKEN=your_token\n   BLUESKY_API_URL=https://bsky.social\n   BLUESKY_USERNAME=your.username\n   BLUESKY_PASSWORD=your_app_password\n   MASTODON_SOURCE_ACCOUNTS=@user@instance\n   BLUESKY_SOURCE_ACCOUNTS=@user.bsky.social\n   DEBUG_MODE=true    # Start with debug mode enabled for safety\n   DEBUG_LEVEL=verbose\n   OPENAI_API_KEY=your_openai_api_key\n   ```\n\n3. Start the development server:\n   ```bash\n   wrangler dev\n   ```\n\n## API Endpoints\n\n- `POST /run` - Execute the bot (30% chance to post)\n- `POST /upload-tweets` - Upload source content\n- `GET /upload-tweets` - Get source content count\n- `POST /test-reply` - Test AI-powered reply generation\n- `POST /check-replies` - Check for and process new replies\n\n## Deployment\n\n1. Configure your environment variables in Cloudflare:\n   ```bash\n   wrangler secret put MASTODON_ACCESS_TOKEN\n   # Repeat for other secrets\n   ```\n\n2. Deploy to Cloudflare Workers:\n   ```bash\n   wrangler deploy\n   ```\n\n## Behavior\n\n- The bot has a 30% chance of posting each time it runs\n- When posting, it will attempt to post to both Mastodon and Bluesky\n- Generated content is based on source content from specified accounts\n- Content is filtered to remove excluded words\n- Debug logs show the random percentage and whether a post was attempted\n\n## Development\n\n- Written in JavaScript\n- Uses Cloudflare Workers for serverless execution\n- Stores source content in Cloudflare KV\n- Implements Markov chain text generation\n- Supports multiple social media platforms\n\n## Reply Behavior\nThe bot uses the following criteria to determine when to reply:\n\n1. **First Interactions**\n   - Always replies to the first interaction in a thread\n   - Helps establish initial engagement\n\n2. **Subsequent Interactions**\n   - 30% chance to reply to follow-up messages\n   - Prevents excessive back-and-forth conversations\n\n3. **Content Filtering**\n   - Skips replies containing words from `EXCLUDED_WORDS`\n   - Won't reply to its own posts\n   - Ignores posts older than 24 hours\n\n4. **Debug Mode**\n   - Set `DEBUG_MODE=true` to see detailed decision logging\n   - Helpful for understanding reply behavior\n\n## Testing Guide\n\n### Testing Reply Generation\nThere are several ways to test the reply functionality:\n\n1. **Using the Test Endpoint**\n   ```bash\n   # Create test-payload.json with your test data\n   {\n     \"postUrl\": \"https://bsky.app/profile/username.bsky.social/post/postid\",\n     \"replyContent\": \"Your test reply content here\"\n   }\n\n   # Test reply generation\n   curl -X POST http://127.0.0.1:8787/test-reply \\\n     -H \"Content-Type: application/json\" \\\n     --data-binary \"@test-payload.json\"\n   ```\n\n2. **Testing Live Reply Behavior**\n   ```bash\n   # First, make the bot post something\n   curl -X POST http://127.0.0.1:8787/run\n\n   # Then reply to that post from another account\n   \n   # Finally, trigger reply checking\n   curl -X POST http://127.0.0.1:8787/check-replies\n   ```\n\n3. **Debug Mode Testing**\n   ```bash\n   # Enable debug mode in .dev.vars\n   DEBUG_MODE=true\n   DEBUG_LEVEL=verbose\n\n   # Run the reply checker to see detailed logs\n   curl -X POST http://127.0.0.1:8787/check-replies\n   ```\n\n### Testing Different Scenarios\n\n1. **First Reply Testing**\n   - Post something from the bot\n   - Reply to it from another account\n   - Run `/check-replies` - bot should always respond\n\n2. **Subsequent Reply Testing**\n   - Continue the conversation\n   - Run `/check-replies` multiple times\n   - Bot should respond ~30% of the time\n\n3. **Content Filter Testing**\n   ```bash\n   # Add test words to .dev.vars\n   EXCLUDED_WORDS=test,spam,ignore\n\n   # Reply to bot with these words\n   # Bot should skip these replies\n   ```\n\n4. **Age Limit Testing**\n   - Reply to an old post (\u003e24h)\n   - Bot should skip these replies\n\n5. **Self-Reply Testing**\n   - Reply to the bot's post using the bot's account\n   - Bot should skip these replies\n\n### Troubleshooting\n\n1. **Check Logs**\n   - Enable verbose logging:\n     ```\n     DEBUG_MODE=true\n     DEBUG_LEVEL=verbose\n     ```\n   - Look for \"Processing notification\" and \"Reply decision\" messages\n\n2. **Common Issues**\n   - API authentication errors: Check credentials in `.dev.vars`\n   - Missing replies: Verify notification fetching is working\n   - Unexpected behavior: Check debug logs for decision reasoning\n\n3. **Testing Environment**\n   - Use `wrangler dev` for local testing\n   - Create test accounts on both platforms\n   - Keep test-payload.json in .gitignore\n\n## License\n\nMIT License - See LICENSE file for details\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjerdog%2Fserverless-social-bot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjerdog%2Fserverless-social-bot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjerdog%2Fserverless-social-bot/lists"}