Wenlan
Wenlan은 소스 기반 AI 지식베이스·LLM 위키로, 문서·결정을 페이지화해 검색·검토·리뷰 가능
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Aggregate calendar availability from many accounts — Google, Outlook/M365, iCloud/Fastmail, plus device-bound work accounts behind Conditional Access — into a single private free/busy ICS feed you subscribe to for personal planning. Read-only, private, never shared externally.
Privacy by construction, with source attribution. AvailCal ingests only busy intervals —
start/end/statusplus a single owner-assigned one-word source label. Titles, descriptions, attendees and locations are stripped at the earliest point. The label becomes each event'sSUMMARY(andCATEGORIES) so you can still tell which calendar a block came from — a coarse tag likeWork,Perso,iCloud, never event content.
Cloud-reachable accounts ─(secret ICS URL / CalDAV)─┐
├─► Container Apps Job (cron, scale-to-zero)
Device-bound accounts ─(local agent → /raw JSON)─────┘ pull → normalize → merge → emit
▼
Blob: /raw/*.json + /merged/availability.ics + /raw/*.ics
▼
Apple Calendar / Thunderbird / Fantastical (ICS subscription, hourly)
A scheduled, scale-to-zero job (hourly cron, no always-on server) pulls every
source, normalizes all times to UTC, merges per-source busy blocks, and writes
one merged availability.ics to object storage. Your calendar clients subscribe
to that object. See docs/ARCHITECTURE.md.
It runs on Cloudflare Workers + Containers + R2 (primary — a Worker cron
drives the merge Container and serves the feed from R2) or an Azure Container
Apps Job + Blob (alternative). The same merge/ image runs on both.
Storage is pluggable. The same image writes to Cloudflare R2 (S3-compatible,
zero egress), Azure Blob, or a local directory — selected by env vars
(AVAILCAL_OUTPUT_DIR > R2 > Azure). For R2, see
infra/cloudflare/README.md.
The only bespoke code is the device-bound local reads (agents) and the
free/busy merge. Everything else reuses existing tools: recurring-ical-events
(recurrence), vdirsyncer (CalDAV), icalendar (parse/emit), native OS calendar
stores (device reads), OS schedulers (agents), and Container Apps (cloud timer).
| Path | What |
|---|---|
merge/ | The Python merge job (pull → normalize → merge → emit) + Dockerfile |
agents/windows/ | Outlook COM exporter + Scheduled Task installer |
agents/macos/ | EventKit exporter + launchd agent installer |
infra/ | Bicep for Storage, Key Vault, and the scheduled Container Apps Job |
.github/workflows/ | CI (lint/test/build) and OIDC deploy |
docs/ | Architecture, getting ICS URLs, subscribing, and the runbook |
sources.example.toml | The source registry (rawname → one-word label) |
az) with the Bicep extension.cd merge
pip install -e '.[dev]'
ruff check .
pytest -q
Copy sources.example.toml to sources.toml and map each raw input (ICS feed,
CalDAV account, device calendar name) to a single-word label. Labels must be
unique single tokens — the job validates this at startup and fails fast.
Follow docs/GET-ICS-URLS.md to obtain each account's
secret ICS URL (Google secret-iCal, Outlook published ICS) or set up CalDAV
(iCloud/Fastmail via vdirsyncer). Work accounts that block published ICS use
the device agents instead.
cd merge
AVAILCAL_SOURCES_TOML=../sources.toml \
AVAILCAL_ICS_FEEDS='GoogPersonal=https://…/basic.ics' \
AVAILCAL_OUTPUT_DIR=./out \
python -m availcal.main
# -> ./out/merged/availability.ics (and ./out/raw/<Label>.ics overlays)
Two supported targets — the same merge/ image runs on both:
Cloudflare (Workers + Containers + R2) — primary. A Worker runs the hourly cron, drives the merge Container, serves the feed from R2, and accepts agent uploads. See worker/README.md and infra/cloudflare/README.md.
wrangler r2 bucket create availcal # one-time
cd worker
npm ci
npm run typecheck # tsc --noEmit
npx wrangler types # validate wrangler.jsonc + bindings
# set secrets once (FEED_TOKEN, AGENT_TOKEN, RUN_TOKEN, AVAILCAL_R2_*, AVAILCAL_ICS_FEEDS):
wrangler secret put FEED_TOKEN # …repeat per secret (see worker/README.md)
npx wrangler deploy # builds+pushes the Container, binds R2, registers cron
# local dev: cp .dev.vars.example .dev.vars && npx wrangler dev
CI runs wrangler types + tsc on every PR; npx wrangler deploy runs from
.github/workflows/deploy-cloudflare.yml (manual/tag).
Azure (Container Apps Job) — alternative.
az acr login --name <ACR_NAME>
docker build -t <ACR_LOGIN_SERVER>/availcal:v1 ./merge
docker push <ACR_LOGIN_SERVER>/availcal:v1
./infra/deploy.sh availcal-rg eastus containerImage=<ACR_LOGIN_SERVER>/availcal:v1
Then load feed secrets into Key Vault / Workers Secrets and trigger a run — see docs/RUNBOOK.md.
여기까지가 README 앞부분입니다. 나머지는 원문에서 읽을 수 있습니다. README 전문 보기 ↗