Automatischer, schlanker Downloader für TU Berlin ISIS (Moodle) — mit Web-UI für Handy, Tablet und PC.
Lädt nur die Kurse und Dateitypen herunter, die du auswählst (z.B. nur PDFs, keine Videos), und legt sie in deiner tubCloud ab. Von dort synchronisiert der Nextcloud-Client die Dateien automatisch auf alle deine Geräte. Läuft komplett kostenlos in der Cloud (GitHub Actions) — dein PC muss nicht laufen.
⚠️ TU-Berlin-spezifisch. Der Login geht über das Shibboleth-SSO der TU Berlin und lädt in die tubCloud. Für andere Unis müsstest duisisdownloader/auth.pyundisisdownloader/webdav.pyanpassen.
🔒 Halte dein Repo privat. Der Sync selbst legt keine Geheimnisse ins Repo (die liegen in GitHub Secrets), aber
courses_cache.jsonenthält die Liste aller Kurse, in denen du eingeschrieben bist. Das ist zwar harmlos, aber persönlich — also privates Repo verwenden.
┌────────────────┐ cron 4h ┌──────────────────┐ WebDAV PUT
│ GitHub Actions │───────────────►│ ISIS-Login → │─────────────► tubCloud /ISIS/
│ sync.yml │ │ filtern → DL │
└────────────────┘ └──────────────────┘
▲ ▲
│ workflow_dispatch │ Nextcloud-Client-Sync
│ │
┌────────────────┐ ┌─────────────────────────┐
│ Web-UI auf │── liest/schreibt courses.json ──►│ Handy / Tablet / PC │
│ Cloudflare P. │── triggert Workflows ────────────► │
└────────────────┘ └─────────────────────────┘
- Web-UI: statische Seite (Vanilla HTML/JS, kein Build) auf Cloudflare Pages — kostenlos und kann aus privaten GitHub-Repos deployen. Greift via GitHub-API auf dein Repo zu, editiert
courses.jsonund stößt die Workflows an. - sync.yml: läuft alle 4 h (oder auf Knopfdruck), holt nur die in
courses.jsonaktivierten Kurse. - refresh-courses.yml: läuft 1× pro Tag (oder auf Knopfdruck), aktualisiert
courses_cache.json— die Liste aller eingeschriebenen ISIS-Kurse für die UI. - State (was schon geladen wurde) liegt in der tubCloud unter
/ISIS/.isisdownloader_state.json, nicht in GitHub → die Skripte sind stateless.
Der Login-Flow (Shibboleth-SSO → Moodle-Web-Service-Token) orientiert sich an Emily3403/isisdl.
Oben auf „Use this template" → „Create a new repository" klicken. Wichtig: Sichtbarkeit auf „Private" stellen. Dann lokal klonen:
git clone https://github.com/<dein-user>/<dein-repo>.git
cd <dein-repo>- https://tubcloud.tu-berlin.de → Profilbild → Einstellungen → Sicherheit.
- Unten „App-Passwort erstellen" → Name z.B.
isisdownloader→ Benutzername und Passwort notieren (beides wird angezeigt — den Benutzernamen brauchst du gleich, er kann von deinem Login abweichen).
Im Repo → Settings → Secrets and variables → Actions → New repository secret:
| Name | Wert |
|---|---|
TU_USERNAME |
dein tubIT-Username |
TU_PASSWORD |
dein tubIT-Passwort |
TUBCLOUD_USERNAME |
der Benutzername aus dem App-Passwort-Dialog (Schritt 1) |
TUBCLOUD_PASSWORD |
das App-Passwort aus Schritt 1 (nicht dein normales Passwort) |
Der WebDAV-Pfad in der tubCloud nutzt intern eine UUID statt deines Login-Namens — das ermittelt das Skript automatisch per OCS-API, du musst dich darum nicht kümmern.
Repo → Actions → „Refresh Course List" → Run workflow. Nach ~30 s hat der Bot courses_cache.json in dein Repo committet.
- Account: https://dash.cloudflare.com/sign-up (gratis, ohne Kreditkarte).
- „Workers & Pages" → „Create application" → Tab „Pages" → „Connect to Git".
- GitHub autorisieren → nur dein Repo auswählen.
- Build-Settings:
- Framework preset: None
- Build command: leer lassen
- Build output directory:
docs
- Save and Deploy → du bekommst eine URL wie
https://<name>.pages.dev/.
wrangler.jsonc im Repo sorgt dafür, dass Cloudflare die statischen Dateien aus docs/ ausliefert (kein Build). Jeder git push auf main löst automatisch ein Re-Deploy aus.
Damit die UI dein Repo lesen/schreiben darf:
- https://github.com/settings/personal-access-tokens/new (Fine-grained).
- Repository access: nur dieses eine Repo.
- Permissions → Repository: Contents = Read and Write, Actions = Read and Write, Metadata = Read (Pflicht).
- Generieren → Token kopieren (wird nur einmal angezeigt).
- Cloudflare-URL im Handy-Browser öffnen.
- Tab „Einstellungen" → Repo (
dein-user/dein-repo), Token, Branch (main) + optional tubCloud-Zugang → Speichern. - Browser-Menü → „Zum Startbildschirm hinzufügen" → App-Icon ist da (PWA).
- Tab „Kurse" → Schalter für die gewünschten Kurse umlegen, optional Filter setzen → Speichern.
- Tab „Status" → „Jetzt syncen" → erster Sync läuft. Die Dateien erscheinen in tubCloud unter
/ISIS/.
Nextcloud-App (oder FolderSync) einrichten und den /ISIS-Ordner für Offline-Sync markieren.
Wird von der UI gepflegt, kann aber auch von Hand editiert werden:
Globale Defaults (z.B. extensions: [pdf], exclude_mime_prefixes: [video/, audio/]) stehen in config.yaml.
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
export TU_USERNAME=... TU_PASSWORD=...
python list_courses.py --print # listet deine Kurse mit IDs
export TUBCLOUD_USERNAME=... TUBCLOUD_PASSWORD=...
python main.py # führt einen Sync aus- Zwei-Faktor-Authentifizierung: Hat dein tubIT-Konto 2FA, funktioniert der automatische Login nicht.
- Es werden nur Datei-Ressourcen aus
core_course_get_contentsgeholt — also Folien, Skripte, PDF-Aufgabenblätter. Anhänge ausmod_assign(Abgabemodule) brauchen einen zusätzlichen API-Call und sind aktuell nicht dabei. - Wird eine Datei in ISIS umbenannt, lädt das Skript sie unter dem neuen Namen erneut — die alte bleibt in tubCloud liegen.
- Der Dateien-Tab der UI liest die State-Datei per Browser-WebDAV aus tubCloud; manche Browser blocken das wegen CORS. Der Sync selbst ist davon nicht betroffen.
isisdownloader/
├── auth.py TU-SSO → Moodle-WS-Token
├── isis.py Moodle-WS API (Kurse, Dateien)
├── webdav.py tubCloud WebDAV (mit OCS-User-ID-Lookup)
├── config.py lädt config.yaml + courses.json
├── state.py State-Tracking in tubCloud
└── sync.py Hauptlogik
main.py CLI-Entry für den Sync
list_courses.py schreibt courses_cache.json
docs/ Web-UI (statisch, für Cloudflare Pages)
.github/workflows/ sync.yml (4h) + refresh-courses.yml (täglich)
MIT — mach damit was du willst. Keine Haftung, kein Support-Anspruch. Kein offizielles Projekt der TU Berlin.
{ "courses": [ { "id": 12345, "name": "Algorithmen und Datenstrukturen", "enabled": true, "extensions": ["pdf", "zip"], "include_regex": "^(Aufgabe|Übung|Vorlesung|Skript)", // optional "exclude_regex": null, // optional "max_file_size_mb": 100 // optional } ] }