No description
- Python 98.4%
- Dockerfile 1.6%
|
|
||
|---|---|---|
| .env.example | ||
| .gitignore | ||
| .python-version | ||
| CLAUDE.md | ||
| compose.yml | ||
| db.py | ||
| Dockerfile | ||
| feed.py | ||
| gts.py | ||
| main.py | ||
| pyproject.toml | ||
| README.md | ||
| tinylog.py | ||
| uv.lock | ||
tinylog
Generates and keeps a tinylog-format .gmi file from public posts on a GoToSocial instance, for serving on a Gemini capsule. Connects to the GoToSocial streaming API for real-time updates and handles adds, edits, and deletes.
Features
- Real-time streaming via GoToSocial WebSocket API (no polling)
- Full backfill of existing public posts on first run
- Propagates edits and deletes
- Self-reply threads collapsed into a single tinylog entry with a
[continued]separator - HTML-to-gemtext conversion: lists, blockquotes, preformatted blocks, footnote-style links
- Skips posts with content warnings, replies to other accounts, non-public posts, local-only posts, and posts that mention other accounts
- Atomically writes the
.gmifile so Agate never serves a partial result - Regenerates the full file on every startup (safe to restart after config changes)
- Generates a
feed.gmicompatible with Gemini antenna aggregators and pings them on every update
Setup
cp .env.example .env
# fill in .env
docker compose up --build -d
Map the output file into your Agate content directory via a volume in compose.yml:
volumes:
- ./data:/app/data
- /var/gemini/capsule/tinylog.gmi:/app/tinylog.gmi
Configuration
All configuration is via environment variables (.env):
| Variable | Required | Default | Description |
|---|---|---|---|
GTS_BASE_URL |
yes | — | Your GoToSocial instance URL |
GTS_ACCESS_TOKEN |
yes | — | OAuth bearer token with read scope |
TINYLOG_TITLE |
no | Tinylog |
Level-1 heading in the .gmi file |
AUTHOR_NAME |
no | — | Author name for the author: metadata line |
AUTHOR_CAPSULE |
no | — | Gemini capsule URL for the author: metadata line |
AUTHOR_AVATAR |
no | — | Avatar emoji (optionally followed by a description) |
AUTHOR_DESCRIPTION |
no | — | Free-text description shown below the title |
TINYLOG_PATH |
no | /app/tinylog.gmi |
Output path inside the container |
FEED_PATH |
no | — | Output path for feed.gmi; required to enable feed generation |
FEED_TITLE |
no | — | Link label in feed.gmi (e.g. Microblog); required to enable feed generation |
FEED_URL |
no | — | Full Gemini URL of feed.gmi; sent to antenna endpoints |
ANTENNA_URLS |
no | — | Comma-separated Gemini antenna submit URLs to ping on each update |
SYNC_SINCE |
no | now |
First-run behaviour (see below) |
LOG_LEVEL |
no | INFO |
DEBUG, INFO, WARNING, ERROR |
GTS access token
Create an application on your GoToSocial instance and complete the OAuth flow to obtain a bearer token with read scope. No write scope is needed.
SYNC_SINCE (first run only)
Controls what happens the very first time the program runs against an empty database. Ignored on subsequent starts.
| Value | Behaviour |
|---|---|
now (default) |
Sets a watermark at the current latest post; no historical posts are included |
all |
Backfills everything GoToSocial can return (paginated) |
2024-05-01 |
Backfills posts from that date onward (ISO date or datetime) |
Development
# Run locally (requires .env)
uv run python main.py
# Override sync behaviour
SYNC_SINCE=all uv run python main.py
There are no automated tests in this project.