Automated Nostr bot that publishes weekly Bitcoin metrics and historical events as NIP-23 long-form articles.
- 📊 Weekly Bitcoin Metrics: Posts current price, hashrate, Bitcoin nodes, Lightning Network stats with historical comparisons (1yr, 3yr)
- 📅 Weekly Historical Events: Posts upcoming week's Bitcoin historical events and timeless reads
- 🔄 Automated Scheduling: Uses cron for reliable scheduled posting (Mondays at 7:10 AM)
- 📝 NIP-23 Long-form Content: Creates rich, Markdown-formatted articles
- 🌐 Multi-relay Support: Publishes to multiple Nostr relays simultaneously
- 📈 Auto-updating CSV: Automatically updates Bitcoin node count CSV file weekly
- ⚡ High Performance: Fetches data in parallel for minimal latency
- 🛡️ Robust Error Handling: Structured logging and graceful degradation for optional metrics
- Go 1.24 or higher
- Nostr private key (hex format)
- Bitcoin Events API key
- Clone or create the project:
cd bitcoin-nostr-bot- Initialize Go module (already done):
go mod init bitcoin-nostr-bot- Install dependencies:
go get github.com/nbd-wtf/go-nostr
go get github.com/robfig/cron/v3
go get github.com/joho/godotenv
go get golang.org/x/sync/errgroup
go get golang.org/x/textOr simply run:
go mod download- Create
.envfile from.env.example:
cp .env.example .env- Edit
.envwith your credentials:
nano .env| Variable | Description | Example |
|---|---|---|
NOSTR_PRIVATE_KEY |
Your Nostr private key (hex) | abc123... |
NOSTR_RELAYS |
Comma-separated relay URLs | wss://relay.damus.io,wss://nos.lol |
EVENTS_API_KEY |
Bitcoin Events API key | your_key_here |
EVENTS_API_URL |
Events API base URL | http://213.176.74.147:3001/api |
METRICS_SCHEDULE |
Cron schedule for combined post | 10 7 * * 1 (Monday 7:10 AM) |
TZ |
Timezone | UTC |
* * * * *
│ │ │ │ │
│ │ │ │ └─── Day of week (0-7, Sunday = 0 or 7)
│ │ │ └───── Month (1-12)
│ │ └─────── Day of month (1-31)
│ └───────── Hour (0-23)
└─────────── Minute (0-59)
Examples:
0 9 * * *- Every day at 9:00 AM0 18 * * 0- Every Sunday at 6:00 PM*/30 * * * *- Every 30 minutes0 */6 * * *- Every 6 hours
go build -o bitcoin-nostr-bot./bitcoin-nostr-bot./bitcoin-nostr-bot -testNote: The Dockerfile uses Go 1.24 to support the parallelization features.
docker-compose up -d --builddocker-compose logs -fdocker-compose downdocker-compose restartNote: The CSV file reachable_bitcoin_nodes.csv is mounted as a volume, so updates persist across container restarts.
Hi bitcoiner. This is your weekly snapshot looking back at Bitcoin years ago.
## 📊 Bitcoin Metrics in Historical Perspective
Take a look at fresh Bitcoin metrics and see how much the network has evolved over the years.
| Metric | Today | 1 Year Ago | 3 Years Ago |
|--------|-------|------------|-------------|
| **Price** | $96,411.00 | $91,400.00 | $16,664.00 |
| **Hashrate** | 1104.75 EH/s | 761.10 EH/s | 271.59 EH/s |
| **Bitcoin Nodes** | 23,350 | 19,499 | 15,317 |
| **LN Nodes** | 16,294 | 15,790 | 13,857 |
| **LN Capacity** | 3,747.73 BTC | 5,261.11 BTC | 5,126.18 BTC |
---
## 📅 Bitcoin History - Nov 17-23
Explore the upcoming Bitcoin history milestones and holidays:
### Monday, Nov 17
- [🛑 S2X Launch Failed](https://bitcoin-calendar.org/en/events/2017-11-17/s2x-launch-failed) (2017)
## 📚 Timeless Reads
...
---
#### Sources
- *Browse hundreds of historical Bitcoin milestones by visiting [bitcoin-calendar.org](https://bitcoin-calendar.org)*
- *Historical events sourced from [Bitcoin Calendar open database](https://github.com/Bitcoin-Calendar/calendar-api-db/tree/main/data)*
- *Price, hashrate and LN data provided by [mempool.space](https://mempool.space/)*
- *Bitcoin nodes data by [Bitnodes](https://bitnodes.io/)*ps aux | grep bitcoin-nostr-botThe bot logs to stdout. Redirect to a file:
./bitcoin-nostr-bot >> bot.log 2>&1 &- Check your private key is correct (64 character hex string)
- Verify relay URLs are correct and accessible
- Check logs for connection errors
- Test with
--testflag
- Verify
EVENTS_API_KEYis correct - Check
EVENTS_API_URLis accessible - Verify you haven't hit rate limits (100 req/min)
- Verify cron syntax is correct
- Check
TZenvironment variable - Remember cron uses UTC by default unless TZ is set
- Default schedule is
10 7 * * 1(Monday at 7:10 AM UTC)
- The bot looks for events in the upcoming week (Monday-Sunday from next Monday)
- If today is Sunday and you run manually, it will fetch next week's events
- Check the Events API has data for those dates
- Ensure
reachable_bitcoin_nodes.csvexists in the project root - Check file permissions (should be readable/writable)
- Verify CSV format:
date,total_nodes(YYYY-MM-DD format) - In Docker, the CSV is mounted as a volume - check volume mount in docker-compose.yml
- The bot automatically resolves CSV path from multiple locations (current dir, parent dir, or default path)
go test ./...Add new formatters:
- Create new file in
formatters/ - Implement
FormattedPostreturn type - Call from scheduler in
main.go
Add new data sources:
- Create new fetcher in
fetchers/ - Add configuration to
config/config.go - Create formatter in
formatters/ - Schedule in
main.go
Customize post format:
- Edit
formatters/metrics.goorformatters/events.go - Markdown is fully supported
- Can add tables, lists, headers, links, etc.
This project is licensed under the MIT License - see the LICENSE file for details.
For issues with:
- Nostr publishing: Check go-nostr documentation
- Bitcoin data: Check mempool.space and Bitnodes API docs
- Events API: Contact API administrator
- Bot functionality: Open an issue with logs
- CSV updates: Check file permissions and Docker volume mounts
- Price, Hashrate & LN: mempool.space API
- Bitcoin Nodes: Bitnodes API (current) + CSV file (historical)
- Historical Events: Bitcoin Calendar API
- Built with go-nostr
- Scheduled with cron
- Parallelization with golang.org/x/sync/errgroup
- Formatting with golang.org/x/text
- Bitcoin data from mempool.space and Bitnodes