Almanac bot for Twitter.
Project description
Almanac Bot
A Twitter bot that tweets historical events (ephemeris) on their anniversary dates. Each day, it finds events that happened on that calendar date (any year) and tweets them with localized text.
Features
- Tweets historical events on their anniversary (month+day matching)
- Supports multiple events per day
- Template variables:
${date}(localized) and${years_ago}(calculated) - Idempotency: won't tweet the same event twice on the same day
- Dry-run mode for testing without sending tweets
- Stateless execution triggered by external scheduler (Ofelia)
Dependencies
- Docker
- Python 3.12+
- PostgreSQL 17.3+
- just (optional, for convenience commands)
Quick Start
1. Create configuration
cp config.ini.default config.ini
Fill in the Twitter API credentials and other settings:
[language]
locale=ca_ES # or en_US, es_ES, etc.
[twitter]
bearer_token=...
consumer_key=...
consumer_secret=...
access_token_key=...
access_token_secret=...
[postgresql]
user=almanac
password=almanac
hostname=postgres
database=almanac
2. Launch with Docker Compose
just docker-up
# or: docker compose up -d
This starts:
- postgres: PostgreSQL database
- almanac-bot: The bot container (kept alive for scheduled execution)
- ofelia: Scheduler that triggers the bot daily at 8:00 AM
3. Load ephemeris data
just docker-load-data
# or: docker exec -it almanac-bot uv run python -m typer almanacbot.data_loader run
CSV format (init_db.csv):
date;text;location
1899-11-29 12:00 Europe/Madrid;El ${date}, avui fa ${years_ago} anys...;(41.38,2.17)
Usage
Manual execution
# Run once (will tweet if there are events for today)
just docker-run
# Dry-run mode (shows what would be tweeted without sending)
just docker-dry-run
Scheduled execution
The bot is automatically triggered by Ofelia at 8:00 AM daily. Check the schedule in compose.yaml:
labels:
ofelia.job-exec.almanac.schedule: "0 0 8 * * *" # Daily at 8 AM
View logs
just docker-logs # Bot logs
just docker-logs-scheduler # Scheduler logs (follow mode)
Development
Run tests
just test # Unit tests
just test-cov # With coverage report
just test-integration # Integration tests (starts postgres automatically)
Linting
just lint # Check for issues
just lint-fix # Auto-fix issues
Build Docker image
just docker-build
Database
Schema
The ephemeris table stores historical events:
CREATE TABLE almanac.ephemeris (
id serial primary key,
date timestamp with time zone not null,
text text not null,
location point default null,
last_tweeted_at timestamp with time zone default null
);
Clean database
just docker-clean-db
Just Commands Reference
just help # Show all available commands
| Command | Description |
|---|---|
just docker-up |
Start all services |
just docker-down |
Stop all services |
just docker-serve |
Start and follow logs |
just docker-load-data |
Load ephemeris from CSV |
just docker-run |
Run bot manually |
just docker-dry-run |
Run without tweeting |
just docker-logs |
View bot logs |
just docker-logs-scheduler |
View scheduler logs |
just docker-build |
Build Docker image |
just docker-clean-db |
Remove database volume |
just test |
Run unit tests |
just test-cov |
Run tests with coverage |
just test-integration |
Run integration tests |
just lint |
Check code style |
just lint-fix |
Fix code style |
Architecture
Ofelia (scheduler)
│
│ triggers daily at 8 AM
▼
┌─────────────────────────────────────────────────────┐
│ almanac-bot │
│ │
│ 1. Query ephemeris for today (month+day match) │
│ 2. Filter out already-tweeted (idempotency) │
│ 3. Tweet each event │
│ 4. Mark as tweeted (last_tweeted_at) │
│ 5. Exit │
└─────────────────────────────────────────────────────┘
│
▼
PostgreSQL
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file almanac_bot-1.0.0.tar.gz.
File metadata
- Download URL: almanac_bot-1.0.0.tar.gz
- Upload date:
- Size: 8.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ae7e1eed33e91ce0ac29b9cf503e4494b875a91ea693d759c9391233d337029b
|
|
| MD5 |
38b2e1c2d6c149b8ad208f2de0ea0dfe
|
|
| BLAKE2b-256 |
74709aca537dff196eed7027b8830aa69a895e4ef25d1731fdf0fee72366a60d
|
Provenance
The following attestation bundles were made for almanac_bot-1.0.0.tar.gz:
Publisher:
publish.yaml on logoff/almanac-bot
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
almanac_bot-1.0.0.tar.gz -
Subject digest:
ae7e1eed33e91ce0ac29b9cf503e4494b875a91ea693d759c9391233d337029b - Sigstore transparency entry: 780359495
- Sigstore integration time:
-
Permalink:
logoff/almanac-bot@eacb9d5e36bd60bde0ae3a22a4a777004a05c86d -
Branch / Tag:
refs/tags/1.0.0 - Owner: https://github.com/logoff
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@eacb9d5e36bd60bde0ae3a22a4a777004a05c86d -
Trigger Event:
push
-
Statement type:
File details
Details for the file almanac_bot-1.0.0-py3-none-any.whl.
File metadata
- Download URL: almanac_bot-1.0.0-py3-none-any.whl
- Upload date:
- Size: 11.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e3a1de3fc5c32bd0754d35bf11dfc11cd3cc6741341b5b180902f2a3e587ef2c
|
|
| MD5 |
993e7d65059e838c8ee08c15cef6b8fd
|
|
| BLAKE2b-256 |
9adc1efdfaa58ef0334dcb24128c16f0f4421a766963a5d65c201f515d5da6e8
|
Provenance
The following attestation bundles were made for almanac_bot-1.0.0-py3-none-any.whl:
Publisher:
publish.yaml on logoff/almanac-bot
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
almanac_bot-1.0.0-py3-none-any.whl -
Subject digest:
e3a1de3fc5c32bd0754d35bf11dfc11cd3cc6741341b5b180902f2a3e587ef2c - Sigstore transparency entry: 780359500
- Sigstore integration time:
-
Permalink:
logoff/almanac-bot@eacb9d5e36bd60bde0ae3a22a4a777004a05c86d -
Branch / Tag:
refs/tags/1.0.0 - Owner: https://github.com/logoff
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@eacb9d5e36bd60bde0ae3a22a4a777004a05c86d -
Trigger Event:
push
-
Statement type: