No description
  • TypeScript 97.7%
  • Dockerfile 2.3%
Find a file
Stefan Siegl 40b5aa8e55 Use markdown() function for proper event announcement rendering
- Import markdown from @fedify/botkit/text (not main export)
- Build markdown string with **bold** labels and [link](url) syntax
- Use two-space line breaks (markdown standard) for <br> tags
- Properly renders: bold labels, line breaks, and clickable links
- Output in ActivityPub: <strong> tags, <br> breaks, <a> links
- Clean, maintainable code with single markdown string
2026-02-21 00:34:49 +01:00
src Use markdown() function for proper event announcement rendering 2026-02-21 00:34:49 +01:00
.dockerignore Add Docker support 2026-02-20 22:27:59 +01:00
.gitignore Add .gitignore to prevent accidental commits of sensitive/runtime files 2026-02-21 00:00:41 +01:00
AGENTS.md Add AGENTS.md with development context for future AI assistance 2026-02-20 22:23:20 +01:00
deno.json Initial bot setup with BotKit and SQLite KV store 2026-02-20 21:05:47 +01:00
deno.lock Implement personalized iCal feed route 2026-02-20 22:12:28 +01:00
docker-compose.yml Update bot bio with Würzburg events focus and owner attribution 2026-02-20 23:38:35 +01:00
Dockerfile Update bot bio with Würzburg events focus and owner attribution 2026-02-20 23:38:35 +01:00
LICENSE Add MIT License and README 2026-02-20 22:01:22 +01:00
README.md Fix repository URL in README 2026-02-20 22:22:18 +01:00

fediCal

A Fediverse bot that announces events and generates personalized iCal feeds.

Features

  • 📅 Announces events to the Fediverse
  • Tracks interactions - star or boost events you're interested in
  • 📆 Generates iCal feeds personalized to each user
  • 🤖 Auto-welcomes new followers with their unique calendar URL
  • 🔒 Privacy-focused - deletes all your data when you unfollow

Architecture

  • Runtime: Deno (TypeScript native, URL imports, built-in testing)
  • Framework: BotKit (Fedify-based ActivityPub framework)
  • Database: SQLite (simple, serverless, sufficient for use case)
  • Web Server: Single port for all endpoints (ActivityPub + API + iCal)

Getting Started

Prerequisites

Installation

git clone https://wuecode.it/stesie/fedical.git
cd fedical

Configuration

Create a .env file or set environment variables (12-factor app):

# Bot configuration
BOT_HANDLE=bot                          # Fediverse handle (without @domain)
BOT_DOMAIN=fedical.example.com          # Your domain
BOT_PORT=8000                           # HTTP port

# Admin API
ADMIN_TOKEN=YOUR_SECURE_TOKEN           # Required for event ingestion/deletion

# Storage
DATA_DIR=./data                         # SQLite database directory

Running

Development:

deno task dev

Production:

deno run --allow-net --allow-read --allow-write --allow-env --unstable-temporal src/main.ts

API

Event Ingestion

Announce a new event or update an existing one:

curl -X POST "http://localhost:8000/api/events" \
  -F "token=YOUR_SECURE_TOKEN" \
  -F "url=https://example.com/event.json"

The JSON should follow Schema.org Event format (JSON-LD).

Response:

{
  "success": true,
  "eventId": "http://example.com/event-123",
  "isNew": true,
  "announced": true,
  "updated": false
}
  • announced: Event was announced to Fediverse (new events with startDate + time only)
  • updated: Existing announcement was updated

Event Deletion

Remove an event and its announcement:

curl -X DELETE "http://localhost:8000/api/events" \
  -F "token=YOUR_SECURE_TOKEN" \
  -F "url=https://example.com/event.json"

Event Format

Events must be valid Schema.org Event JSON-LD:

{
  "@context": "http://schema.org",
  "@type": "Event",
  "@id": "unique-event-id",
  "name": "Concert Name",
  "description": "Event description",
  "startDate": "2026-05-20T20:00:00",
  "endDate": "2026-05-20T23:00:00",
  "location": {
    "@type": "Place",
    "name": "Venue Name"
  },
  "url": "https://example.com/event"
}

Announcement Rules

Events are announced to the Fediverse if:

  • They have a startDate with time component (ISO 8601 with 'T')
  • They are not cancelled or rescheduled
  • They don't have subEvents (parent events with multiple dates)

Events are stored but not announced if they have subEvents (to avoid duplicate announcements).

Database

SQLite database with three main tables:

  • events: Event metadata and raw JSON
  • actors: Follower information with unique iCal tokens
  • interactions: User star/boost interactions

Data is automatically deleted when users unfollow the bot.

License

MIT License - See LICENSE file for details.

Contributing

Contributions welcome! Please feel free to submit a Pull Request.