{"id":50309344,"url":"https://github.com/dknauss/fedibots","last_synced_at":"2026-05-28T19:30:24.729Z","repository":{"id":346033427,"uuid":"1182666119","full_name":"dknauss/fedibots","owner":"dknauss","description":"PHP framework for creating write-only ActivityPub fediverse bots","archived":false,"fork":false,"pushed_at":"2026-04-05T20:19:41.000Z","size":74,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-05T22:16:24.495Z","etag":null,"topics":["activitypub","bots","fediverse","mastodon","php"],"latest_commit_sha":null,"homepage":"https://github.com/dknauss/fedibots","language":"PHP","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/dknauss.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":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-15T20:19:52.000Z","updated_at":"2026-04-05T20:19:38.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dknauss/fedibots","commit_stats":null,"previous_names":["dknauss/fedibots"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dknauss/fedibots","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dknauss%2Ffedibots","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dknauss%2Ffedibots/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dknauss%2Ffedibots/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dknauss%2Ffedibots/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dknauss","download_url":"https://codeload.github.com/dknauss/fedibots/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dknauss%2Ffedibots/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33624202,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-28T02:00:06.440Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["activitypub","bots","fediverse","mastodon","php"],"created_at":"2026-05-28T19:30:23.821Z","updated_at":"2026-05-28T19:30:24.721Z","avatar_url":"https://github.com/dknauss.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fedibots\n\nA PHP framework for creating write-only ActivityPub bots on the fediverse.\n\nInspired by [Terence Eden's ActivityBot](https://gitlab.com/edent/activity-bot/), fedibots is a clean-room implementation that provides a reusable template for spinning up fediverse bots. Each bot is a clone of this repo with its own configuration and content provider.\n\n## Requirements\n\n- PHP 8.2+ with OpenSSL and cURL extensions\n- A web server (Apache or nginx) with HTTPS\n- A (sub)domain pointing to the bot's directory\n\nNo database. No Composer dependencies at runtime. No containers.\n\n## Quick Start\n\n```bash\n# Clone the repo as your bot\ngit clone https://github.com/dknauss/fedibots.git my-bot\ncd my-bot\n\n# Run interactive setup (generates keys, creates .env)\nphp bin/setup.php\n\n# Edit the content provider with your bot's logic\nnano content/ContentProvider.php\n\n# Test a dry-run post\nphp bin/post.php --dry-run\n\n# Deploy to a web server, then verify\nphp bin/verify.php https://my-bot.example.com\n```\n\nSet `BASE_URL` in `.env` to the bot's final canonical HTTPS URL. Scheduled CLI posts and HTTP signatures use that value.\n\n## How It Works\n\nEach bot is a standalone ActivityPub server. Other fediverse users can search for `@botname@yourdomain.com`, follow it, and see posts in their timeline.\n\n**Architecture:**\n\n```\ncontent/ContentProvider.php   \u003c-- Your content logic\n        |\n        v\nbin/post.php (cron)  --\u003e  Outbox  --\u003e  Delivery (multi-cURL)\n                                          |\n                                          v\n                                    Followers' inboxes\n```\n\n**Endpoints served by `index.php`:**\n\n| Path | Purpose |\n|------|---------|\n| `/.well-known/webfinger` | Account discovery |\n| `/.well-known/nodeinfo` | Server metadata |\n| `/{username}` | Actor profile (JSON-LD) |\n| `/inbox` | Receive follow/unfollow |\n| `/outbox` | Published posts collection |\n| `/posts/{id}` | Individual published Note |\n| `/followers` | Follower list |\n| `/action/send` | Create \u0026 broadcast a post (POST, password-protected) |\n\n## Creating Your Bot\n\n### 1. Content Provider\n\nEdit `content/ContentProvider.php` to implement the `ContentProviderInterface`:\n\n```php\n\u003c?php\nuse Fedibots\\Content\\ContentProviderInterface;\nuse Fedibots\\Content\\Post;\n\nfinal class ContentProvider implements ContentProviderInterface\n{\n    public function generatePost(): ?Post\n    {\n        return new Post(\n            content: 'Your bot post content here.',\n            hashtags: ['Bot', 'Fediverse'],\n            language: 'en',\n        );\n    }\n\n    public function getName(): string { return 'My Bot'; }\n    public function getStatus(): array { return ['ready' =\u003e true]; }\n}\n```\n\nReturn `null` from `generatePost()` to skip posting (e.g., if content is exhausted for the day).\n\n### 2. Schedule Posts\n\nAdd a cron job to post on a schedule:\n\n```bash\n# Post daily at 2 PM UTC\n0 14 * * * /usr/bin/php /path/to/my-bot/bin/post.php\n\n# Or via the HTTP API\n0 14 * * * curl -X POST -d \"content=Hello\u0026password=yourpass\" https://my-bot.example.com/action/send\n```\n\n### 3. Web Server Config\n\n**Apache** — the included `.htaccess` handles rewrites. Ensure `mod_rewrite` is enabled.\n\n**nginx:**\n\n```nginx\nserver {\n    listen 443 ssl;\n    server_name my-bot.example.com;\n    root /var/www/my-bot;\n    index index.php;\n\n    location / {\n        rewrite ^/(.*)$ /index.php?path=$1 last;\n    }\n\n    location ~ \\.php$ {\n        fastcgi_pass unix:/run/php/php-fpm.sock;\n        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n        include fastcgi_params;\n    }\n\n    # Block access to sensitive files\n    location ~ /\\.(env|git|htaccess) { deny all; }\n    location ~ ^/(data|content|src|bin|tests|vendor)/ { deny all; }\n}\n```\n\n## Example: WordPress Security Tips Bot\n\nThe `content/examples/wp-security/` directory contains a complete reference bot that posts daily security tips from the [WordPress Security Benchmark](https://github.com/dknauss/wp-security-benchmark).\n\n```bash\n# Import tips from the Benchmark\nphp bin/import-tips.php /path/to/WordPress-Security-Benchmark.md\n\n# Copy the example into place\ncp content/examples/wp-security/ContentProvider.php content/ContentProvider.php\ncp content/examples/wp-security/tips.json content/tips.json\n```\n\n50 tips across 13 security domains. At one post per day, that's ~7 weeks before cycling.\n\n## CLI Tools\n\n| Command | Purpose |\n|---------|---------|\n| `php bin/setup.php` | Interactive setup wizard |\n| `php bin/keygen.php` | Generate RSA keypair |\n| `php bin/post.php` | Trigger a post (use with cron) |\n| `php bin/post.php --dry-run` | Preview post without sending |\n| `php bin/verify.php` | Check local deployment health |\n| `php bin/verify.php https://...` | Also test live endpoints |\n| `php bin/import-tips.php FILE` | Parse Benchmark markdown into tips.json |\n\n## Development\n\n```bash\ncomposer install --dev\nvendor/bin/phpunit\n```\n\n36 tests, 210 assertions covering Post, Signature, FlatFile storage, and ContentProvider.\n\n## Project Structure\n\n```\nfedibots/\n├── index.php              # Front controller\n├── .htaccess              # Apache rewrites\n├── .env.example           # Config template\n├── src/\n│   ├── Config.php\n│   ├── Http/              # Router, Request\n│   ├── ActivityPub/       # WebFinger, Actor, Inbox, Outbox, Signature, Delivery\n│   ├── Storage/           # FlatFile (JSON on disk)\n│   └── Content/           # Post, ContentProviderInterface\n├── content/               # Your bot's content provider\n│   └── examples/          # Reference implementations\n├── bin/                   # CLI tools\n├── data/                  # Runtime data (gitignored)\n└── tests/                 # PHPUnit tests\n```\n\n## Acknowledgments\n\n- [Terence Eden's ActivityBot](https://gitlab.com/edent/activity-bot/) — the inspiration for this project\n- [ActivityPub specification](https://www.w3.org/TR/activitypub/)\n- [Delightful ActivityPub Development](https://codeberg.org/fediverse/delightful-activitypub-development)\n\n## License\n\nMIT (code) / CC BY-SA 4.0 (content files)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdknauss%2Ffedibots","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdknauss%2Ffedibots","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdknauss%2Ffedibots/lists"}