Metadata-Version: 2.4
Name: kulms
Version: 0.1.2
Summary: Python client and CLI for KULMS/Sakai Direct API
Project-URL: Repository, https://github.com/youseiushida/kulms
Project-URL: Issues, https://github.com/youseiushida/kulms/issues
License-File: LICENSE
Requires-Python: >=3.12
Requires-Dist: httpx>=0.28.1
Requires-Dist: keyring>=25.7.0
Requires-Dist: kuauth>=0.2.3
Requires-Dist: platformdirs>=4.9.6
Requires-Dist: pydantic>=2.13.3
Requires-Dist: rich>=15.0.0
Requires-Dist: typer>=0.24.2
Description-Content-Type: text/markdown

# kulms

[![PyPI version](https://img.shields.io/pypi/v/kulms.svg)](https://pypi.org/project/kulms/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Context7 Indexed](https://img.shields.io/badge/Context7-Indexed-047857)](https://context7.com/youseiushida/kulms)
[![Context7 llms.txt](https://img.shields.io/badge/Context7-llms.txt-047857)](https://context7.com/youseiushida/kulms/llms.txt)

`kulms` は、京都大学の KULMS を扱うための Python ライブラリ兼 CLI です。
Sakai Direct API をそのまま触らなくても、KULMS で見慣れた単位でコース、リソース、課題、お知らせ、カレンダーを扱えます。

- CLI として使って、課題確認や授業資料のダウンロードをしたい人向け。
- Python ライブラリとして使って、KULMS をスクリプトから触りたい人向け。
- 高水準 API がまだない箇所は `kulms direct` や `client.direct` で直接叩けます（Sakai APIにはないKULMS上でのWebページも取得可能です）。

## インストール

Python 3.12 以上が必要です。

CLI として使うなら:

```powershell
uv tool install kulms
uv tool update-shell
```

または:

```powershell
pipx install kulms
```

ライブラリとして使うなら:

```powershell
python -m pip install kulms
```

## 最初に必要なもの

最初に用意するものは次の 3 つです。

- ECS-ID などのユーザー名
- パスワード
- 現在有効なワンタイムパスワード、または TOTP シークレット

TOTP シークレットは、[京大の多要素認証マニュアル](https://www.iimc.kyoto-u.ac.jp/ja/services/account/mfa/manuals) に従って認証アプリを登録する際の QR コードに埋め込まれた `otpauth://totp/...?secret=XXXX&...` の `secret` パラメータです。
登録後は QR が再表示されないことが多いので、登録画面で控えておくのが安全です。すでに控えていない場合は、一度アプリを解除して再登録が必要になることがあります。
これを登録時に控えていない場合、あとから使う方法は次のどちらかになります。

- CLI では、ログインや更新のたびにワンタイムパスワードを入力する
- ライブラリでは、`onetime_password=...` または `otp_callback=...` を使う

毎回 OTP を手入力したくないなら、多要素認証を再登録して TOTP シークレットを控え直す必要があります。

## CLI として使う

CLIを使う際にまずログインが必要です。

```powershell
kulms auth login
```

`kulms auth login` では TOTP シークレットを keyring に保存するか聞かれます。

- 保存する場合: 一度だけ TOTP シークレットを入力します。以後 `kulms auth refresh` で OTP の手入力なしにセッション更新できます。
- 保存しない場合: その場でワンタイムパスワードを入力します。TOTP シークレットは保存しません。

ログイン後は、まず次のコマンドを使うことが多いです。

```powershell
kulms courses                                      # 履修中のコース一覧を見る
kulms assignments --status OPEN                    # 未対応の課題を見る
kulms announcements --days 7                       # 直近 7 日のお知らせを見る
kulms calendar --from 2026-04-01 --to 2026-04-30  # 指定期間の予定を見る
```

授業資料を見たい、落としたい場合は `kulms courses` で `COURSE_ID` を確認してから使います。

```powershell
kulms resources COURSE_ID             # 授業のリソース一覧を見る
kulms resources COURSE_ID --download  # 授業のリソースをダウンロードする
```

認証まわりでよく使うコマンド:

```powershell
kulms auth status   # 保存済み資格情報とセッション状態を確認する
kulms auth refresh  # セッションを更新する
kulms auth logout   # セッションだけ削除する
kulms auth forget   # 資格情報とセッションを両方削除する
```

アカウントを分けたい場合は `--profile` を付けます。

```powershell
kulms --profile main auth login  # profile=main でログインする
kulms --profile main courses     # profile=main のコース一覧を見る
```

高水準コマンドで足りない場合は、`kulms direct` で Direct API を直接呼べます。
CLI では、次のどちらも使えます。

- KULMS のドメイン以降のパスを渡す
- KULMS の完全な URL をそのまま渡す

`site` のような短い名前を書くと `/direct/site.json` として扱われます。

```powershell
kulms direct get site                                                   # 短い名前を渡す
kulms direct get /direct/user/current.json                              # ドメイン以降のパスを渡す
kulms direct get https://lms.gakusei.kyoto-u.ac.jp/direct/user/current.json  # 完全な URL を渡す
kulms direct get /portal --raw                                          # HTML をそのまま見る
```

## ライブラリとして使う

最短は `KULMSClient.from_credentials()` です。

TOTP シークレットを持っている場合:

```python
from kulms import KULMSClient

with KULMSClient.from_credentials(
    username="YOUR_USERNAME",
    password="YOUR_PASSWORD",
    totp_secret="YOUR_TOTP_SECRET",  # MFA 登録時に控えた TOTP シークレット
) as client:
    for course in client.courses.list():  # コース一覧を取得する
        print(course.id, course.title)
```

TOTP シークレットを保存したくない、または持っていない場合は、今この瞬間に有効な OTP を直接渡す方法があります。

```python
from kulms import KULMSClient

with KULMSClient.from_credentials(
    username="YOUR_USERNAME",
    password="YOUR_PASSWORD",
    onetime_password="123456",  # 現在有効なワンタイムパスワードを直接渡す
) as client:
    assignments = client.assignments.list(status=["OPEN"])  # 未対応の課題を取る
    for item in assignments:
        print(item.title, item.status)
```

対話的に OTP を入力させたい場合は `otp_callback` も使えます。

```python
from kulms import KULMSClient

with KULMSClient.from_credentials(
    username="YOUR_USERNAME",
    password="YOUR_PASSWORD",
    otp_callback=lambda: input("OTP: "),  # 必要になった時点で OTP を入力する
) as client:
    assignments = client.assignments.list(status=["OPEN"])
    for item in assignments:
        print(item.title, item.status)
```

高水準 API:

- `client.courses`
- `client.resources`
- `client.assignments`
- `client.announcements`
- `client.calendar`
- `client.users`
- `client.sessions`
- `client.direct`

例:

```python
items = client.resources.list("COURSE_ID")
news = client.announcements.list(limit=10)
events = client.calendar.list(first_date="2026-04-01", last_date="2026-04-30")
raw = client.direct.get_json("site")
```

高水準 API で足りない場合は、`client.direct` で Direct API を直接呼べます。
`client.direct.get_json()` は JSON を返すエンドポイント向けです。
普通の HTML ページを取りたい場合は `client.direct.request("GET", ...)` を使います。
`client.direct.request()` は `/direct/...`、`/access/...`、`/portal/...`、絶対 URL を受け付けます。

```python
from kulms import KULMSClient

with KULMSClient.from_credentials(
    username="YOUR_USERNAME",
    password="YOUR_PASSWORD",
    otp_callback=lambda: input("OTP: "),
) as client:
    print(client.direct.get_json("site"))  # JSON を返す Direct API を呼ぶ
    print(client.direct.get_json("/direct/user/current.json"))  # JSON を返すパスを渡す

    response = client.direct.request("GET", "/portal")  # 普通の HTML ページを取る
    print(response.text)
```

## セキュリティ

`kulms` は資格情報とセッションを分けて扱います。

- ユーザー名、パスワード、TOTP シークレットは `keyring` に保存されます
- セッション Cookie はユーザーキャッシュディレクトリに保存されます
- `kulms auth status` で保存状態とセッションファイルの場所を確認できます

注意点:

- TOTP シークレットを保存すると便利ですが、利用する端末が実質的に「パスワード + 二要素」の両方を持つことになります
- 共有 PC や管理されていない端末では、TOTP シークレットを保存しない方が安全です
- 少しでもリスクを下げたいなら、TOTP シークレットは保存せず、ログインや更新ごとに OTP を入力してください
- `kulms auth logout` はセッションだけ消します
- `kulms auth forget` はセッションと保存済み資格情報を両方消します

## License

MIT. See [LICENSE](LICENSE).
