# nes-recycle

ネスプレッソの使用済みカプセル回収フォームを、CLI から補助する macOS 向けツールです。

このツールはブラウザ自動操作ではなく、**HTTP POST ベース**で動作します。

- 初回起動時にプロフィール情報を登録
- プロフィールは **macOS Keychain** に保存
- カプセル種類のデフォルト値も Keychain に保存
- カプセル種類は **数字 1〜3** で選択
- 実行時は可変項目だけを指定
- まず確認画面相当を生成して主要項目を CLI に表示
- `Yes/No` で `Yes` を選んだときだけ本送信

フォーム側の HTML が古く、ブラウザ自動化に頼りづらいため、この方式を採用しています。

## 前提

- macOS
- Homebrew
- フォームサイトへ HTTPS アクセスできること

## インストール

Homebrew でインストールします。

```sh
brew tap rioriost/nes_recycle
brew install nes_recycle
```

## 使い方

基本実行例:

```sh
nes_recycle
```

日付・時間帯・バッグ数を指定する例:

```sh
nes_recycle --date 2026-03-15 --time 午前 --bags 2
```

カプセル種類を数字で指定する例:

```sh
nes_recycle --capsule-type 2
```

確認画面相当の生成だけ行い、本送信しない例:

```sh
nes_recycle --preview-only
```

確認プロンプトを省略して本送信まで進む例:

```sh
nes_recycle --date 2026-03-15 --time 午前 --bags 2 --yes
```

通信せず、設定内容だけ確認する例:

```sh
nes_recycle --dry-run
```

ヘルプを確認する場合:

```sh
nes_recycle --help
```

## 動作フロー

この CLI は次の流れで動きます。

1. Keychain から保存済みプロフィールを読み込む
2. `--date` `--time` `--bags` `--capsule-type` などの可変項目を受け取る
3. フォームの確認画面相当を HTTP POST で生成する
4. 主要項目を CLI に表示する
5. `y` / `n` で確認する
6. `y` のときだけ本送信する

## 主なオプション

- `--date`
  - `YYYY-MM-DD`
  - 省略時は、引数解析の後でフォームサイトの `get_cal_day` レスポンスを取得して、**その時点で指定可能な最小日付**を自動設定
  - そのため、起動直後ではなく、実際に実行へ進む段階で日付解決を行います
- `--time`
  - `指定なし / 午前 / 14時～16時 / 16時～18時 / 18時～21時`
- `--capsule-type`
  - `1 / 2 / 3`
  - 省略時は Keychain に保存したデフォルト値を使用
  - 対応は次の通り
    - `1`: オリジナル
    - `2`: ヴァーチュオ
    - `3`: オリジナルとヴァーチュオ
- `--bags`
  - `1` 以上 `10` 以下
  - 省略時の初期値は `1`
- `--preview-only`
  - 確認画面相当の生成だけ行い、本送信しない
- `--yes`
  - 確認プロンプトを省略して本送信まで進む
- `--dry-run`
  - 通信を行わず、読み込まれた設定内容だけ確認する
- `--reset-profile`
  - 保存済みプロフィールを破棄して再登録する

## プロフィール保存について

このツールは `profile.json` のようなファイルを使わず、プロフィール情報を **macOS Keychain** に保存します。

- サービス名: `st.rio.nes_recycle`
- アカウント名: `profile`

保存される項目:

- ネスプレッソのお客様番号
- 姓
- 名
- 郵便番号
- 回収先住所（都道府県から番地まで）
- 回収先住所（アパート・マンション名と部屋番号）
- 電話番号
- メールアドレス
- カプセル種類のデフォルト値

## カプセル種類のデフォルト値

カプセル種類は、Keychain には**文字列ではなく数字**で保存されます。

- `1`: オリジナル
- `2`: ヴァーチュオ
- `3`: オリジナルとヴァーチュオ

たとえば `2` が保存されていれば、`--capsule-type` を省略した実行時は `ヴァーチュオ` として送信されます。

## 初回起動時

Keychain にプロフィールが未登録の場合、CLI 上で各項目の入力を求められます。  
入力後、その内容は Keychain に保存され、次回以降は再利用されます。

カプセル種類のデフォルト値は、次の数字で入力します。

- `1`: オリジナル
- `2`: ヴァーチュオ
- `3`: オリジナルとヴァーチュオ

## 再初期化されるケース

保存済みプロフィールに問題がある場合は、再入力フローが始まります。

例:

- 保存済みデータが壊れている
- 必須項目が欠けている
- 値の形式が不正

## 再登録時の既定値再利用

プロフィールを再登録する場合、既存の保存内容が読めれば、各項目に既定値として表示されます。  
そのまま使いたい項目は Enter のみで確定し、変更したい項目だけ入力し直せます。

カプセル種類のデフォルト値は、たとえば `1:オリジナル` のような形で既定値表示される想定です。

## 入力値の簡易バリデーション

初期設定時には、以下の簡易チェックを行います。

- お客様番号
  - 7桁または8桁の数字
  - 7桁で入力した場合は、保存時に先頭へ `0` を補って 8 桁化
- 郵便番号
  - 7桁の数字
- 電話番号
  - 10桁または11桁の数字
- メールアドレス
  - 簡易的なメールアドレス形式
- カプセル種類のデフォルト値
  - `1 / 2 / 3` のいずれか

なお、郵便番号や電話番号は、ハイフン付きで入力しても内部で数字のみに正規化されます。

バッグ数は Keychain には保存せず、CLI 実行時に指定します。省略時の初期値は常に `1` です。

## 日付のデフォルト値について

`--date` を省略した場合、このツールは固定ロジックを使わず、フォームサイト側のカレンダー設定を取得してデフォルト日付を決めます。

この取得処理は、引数定義時ではなく、**引数解析後に必要なときだけ**実行されます。

具体的には、フォームトップを取得したうえで `get_cal_day` のレスポンスを参照し、少なくとも次の値を使って最小指定可能日を計算します。

- 締切時刻（`shime_time_h`, `shime_time_m`）
- 何日後から指定可能か（`afer_day_text`）
- カレンダー制御を使うかどうか（`flg_use_calender`）

そのため、従来のような「午前なら翌日、午後なら翌々日」という固定挙動ではなく、**フォームサイトがその時点で許可している最小日付**に追従します。

また、`--date` を明示した場合でも、指定日がその最小日付より前なら CLI 側でエラーにします。

この方式により、フォームサイトの一時的な通信失敗があっても、少なくとも引数解析そのものでは落ちにくくなっています。

## dry-run について

`--dry-run` では通信を行わず、現在使用される設定だけを表示します。

```sh
nes_recycle --dry-run
```

出力にはマスク済みのプロフィール情報が含まれます。  
画面共有やログ保存時には取り扱いに注意してください。

`capsule_type` はコードと表示名の両方を確認できる形式を想定しています。

## preview-only について

`--preview-only` では、フォームの確認画面相当を生成し、主要項目を CLI に表示します。  
本送信は行いません。

```sh
nes_recycle --preview-only
```

送信前の内容確認に向いています。

## Keychain での確認・削除

macOS の「キーチェーンアクセス」アプリや `security` コマンドで確認・削除できます。

保存内容の確認例:

```sh
security find-generic-password -s st.rio.nes_recycle -a profile -w
```

削除例:

```sh
security delete-generic-password -s st.rio.nes_recycle -a profile
```

削除後に再度 `nes_recycle` を実行すると、プロフィール再登録フローが始まります。

CLI から再登録したい場合:

```sh
nes_recycle --reset-profile
```

## 注意事項

- このツールは外部フォームの現行仕様に依存します
- フォーム側の HTML や POST パラメータ仕様が変わると、動作しなくなる可能性があります
- 確認画面の生成に成功しても、本送信後の完了判定はフォーム側表示に依存します
- 最終的には受信メールや実際の受付結果も確認してください

## トラブルシューティング

### 確認画面生成時に入力エラーになる

フォーム側のバリデーション結果が CLI に表示されます。  
特に次を確認してください。

- 郵便番号が実在するか
- 電話番号の桁数が正しいか
- 回収希望日が、その時点でフォームサイト側に許可されている最小日付以降か
- バッグ数が `1`〜`10` の範囲か
- カプセル種類が `1`〜`3` の範囲か

### 保存済みプロフィールを修正したい

次のコマンドで再登録できます。

```sh
nes_recycle --reset-profile
```

### Keychain の読み込みや保存に失敗する

- macOS の `security` コマンドが利用できるか確認してください
- キーチェーンへのアクセス許可ダイアログが出た場合は許可してください
- いったん登録情報を削除して再登録してください

```sh
security delete-generic-password -s st.rio.nes_recycle -a profile
nes_recycle --reset-profile
```

### 本送信後に成功判定できない

フォーム側の完了画面文言が変わると、自動判定できないことがあります。  
その場合は次を確認してください。

- 受信メール
- 実際の受付結果
- フォーム側の表示内容

## 補足

このプロジェクトは、フォーム入力を「毎回ブラウザで手作業する負担」を減らすことを目的にしています。  
固定値は Keychain に保存し、毎回変わる値だけを CLI から与える運用を想定しています。
","edit_agent_output":{"raw_edits":"```\n# nes-recycle\n\nネスプレッソの使用済みカプセル回収フォームを、CLI から補助する macOS 向けツールです。\n\nこのツールはブラウザ自動操作ではなく、**HTTP POST ベース**で動作します。\n\n- 初回起動時にプロフィール情報を登録\n- プロフィールは **macOS Keychain** に保存\n- カプセル種類のデフォルト値も Keychain に保存\n- カプセル種類は **数字 1〜3** で選択\n- 実行時は可変項目だけを指定\n- まず確認画面相当を生成して主要項目を CLI に表示\n- `Yes/No` で `Yes` を選んだときだけ本送信\n\nフォーム側の HTML が古く、ブラウザ自動化に頼りづらいため、この方式を採用しています。\n\n## 前提\n\n- macOS\n- Python 3.11 以上\n- フォームサイトへ HTTPS アクセスできること\n\n## インストール\n\n依存関係を入れます。\n\n```sh\nuv sync\n```\n\n## 使い方\n\n基本実行例:\n\n```sh\nuv run nes_recycle\n```\n\n日付・時間帯・バッグ数を指定する例:\n\n```sh\nuv run nes_recycle --date 2026-03-15 --time 午前 --bags 2\n```\n\nカプセル種類を数字で指定する例:\n\n```sh\nuv run nes_recycle --capsule-type 2\n```\n\n確認画面相当の生成だけ行い、本送信しない例:\n\n```sh\nuv run nes_recycle --preview-only\n```\n\n確認プロンプトを省略して本送信まで進む例:\n\n```sh\nuv run nes_recycle --date 2026-03-15 --time 午前 --bags 2 --yes\n```\n\n通信せず、設定内容だけ確認する例:\n\n```sh\nuv run nes_recycle --dry-run\n```\n\nモジュールとして実行する場合:\n\n```sh\nuv run python -m nes_recycle.main\n```\n\nヘルプを確認する場合:\n\n```sh\nuv run nes_recycle --help\n```\n\n## 動作フロー\n\nこの CLI は次の流れで動きます。\n\n1. Keychain から保存済みプロフィールを読み込む\n2. `--date` `--time` `--bags` `--capsule-type` などの可変項目を受け取る\n3. フォームの確認画面相当を HTTP POST で生成する\n4. 主要項目を CLI に表示する\n5. `y` / `n` で確認する\n6. `y` のときだけ本送信する\n\n## 主なオプション\n\n- `--date`\n  - `YYYY-MM-DD`\n  - 省略時は、引数解析の後でフォームサイトの `get_cal_day` レスポンスを取得して、**その時点で指定可能な最小日付**を自動設定\n  - そのため、起動直後ではなく、実際に実行へ進む段階で日付解決を行います\n- `--time`\n  - `指定なし / 午前 / 14時～16時 / 16時～18時 / 18時～21時`\n- `--capsule-type`\n  - `1 / 2 / 3`\n  - 省略時は Keychain に保存したデフォルト値を使用\n  - 対応は次の通り\n    - `1`: オリジナル\n    - `2`: ヴァーチュオ\n    - `3`: オリジナルとヴァーチュオ\n- `--bags`\n  - `1` 以上 `10` 以下\n  - 省略時の初期値は `1`\n- `--preview-only`\n  - 確認画面相当の生成だけ行い、本送信しない\n- `--yes`\n  - 確認プロンプトを省略して本送信まで進む\n- `--dry-run`\n  - 通信を行わず、読み込まれた設定内容だけ確認する\n- `--reset-profile`\n  - 保存済みプロフィールを破棄して再登録する\n\n## プロフィール保存について\n\nこのツールは `profile.json` のようなファイルを使わず、プロフィール情報を **macOS Keychain** に保存します。\n\n- サービス名: `st.rio.nes_recycle`\n- アカウント名: `profile`\n\n保存される項目:\n\n- ネスプレッソのお客様番号\n- 姓\n- 名\n- 郵便番号\n- 回収先住所（都道府県から番地まで）\n- 回収先住所（アパート・マンション名と部屋番号）\n- 電話番号\n- メールアドレス\n- カプセル種類のデフォルト値\n\n## カプセル種類のデフォルト値\n\nカプセル種類は、Keychain には**文字列ではなく数字**で保存されます。\n\n- `1`: オリジナル\n- `2`: ヴァーチュオ\n- `3`: オリジナルとヴァーチュオ\n\nたとえば `2` が保存されていれば、`--capsule-type` を省略した実行時は `ヴァーチュオ` として送信されます。\n\n## 初回起動時\n\nKeychain にプロフィールが未登録の場合、CLI 上で各項目の入力を求められます。  \n入力後、その内容は Keychain に保存され、次回以降は再利用されます。\n\nカプセル種類のデフォルト値は、次の数字で入力します。\n\n- `1`: オリジナル\n- `2`: ヴァーチュオ\n- `3`: オリジナルとヴァーチュオ\n\n## 再初期化されるケース\n\n保存済みプロフィールに問題がある場合は、再入力フローが始まります。\n\n例:\n\n- 保存済みデータが壊れている\n- 必須項目が欠けている\n- 値の形式が不正\n\n## 再登録時の既定値再利用\n\nプロフィールを再登録する場合、既存の保存内容が読めれば、各項目に既定値として表示されます。  \nそのまま使いたい項目は Enter のみで確定し、変更したい項目だけ入力し直せます。\n\nカプセル種類のデフォルト値は、たとえば `1:オリジナル` のような形で既定値表示される想定です。\n\n## 入力値の簡易バリデーション\n\n初期設定時には、以下の簡易チェックを行います。\n\n- お客様番号\n  - 7桁または8桁の数字\n  - 7桁で入力した場合は、保存時に先頭へ `0` を補って 8 桁化\n- 郵便番号\n  - 7桁の数字\n- 電話番号\n  - 10桁または11桁の数字\n- メールアドレス\n  - 簡易的なメールアドレス形式\n- カプセル種類のデフォルト値\n  - `1 / 2 / 3` のいずれか\n\nなお、郵便番号や電話番号は、ハイフン付きで入力しても内部で数字のみに正規化されます。\n\nバッグ数は Keychain には保存せず、CLI 実行時に指定します。省略時の初期値は常に `1` です。\n\n## 日付のデフォルト値について\n\n`--date` を省略した場合、このツールは固定ロジックを使わず、フォームサイト側のカレンダー設定を取得してデフォルト日付を決めます。\n\nこの取得処理は、引数定義時ではなく、**引数解析後に必要なときだけ**実行されます。\n\n具体的には、フォームトップを取得したうえで `get_cal_day` のレスポンスを参照し、少なくとも次の値を使って最小指定可能日を計算します。\n\n- 締切時刻（`shime_time_h`, `shime_time_m`）\n- 何日後から指定可能か（`afer_day_text`）\n- カレンダー制御を使うかどうか（`flg_use_calender`）\n\nそのため、従来のような「午前なら翌日、午後なら翌々日」という固定挙動ではなく、**フォームサイトがその時点で許可している最小日付**に追従します。\n\nまた、`--date` を明示した場合でも、指定日がその最小日付より前なら CLI 側でエラーにします。\n\nこの方式により、フォームサイトの一時的な通信失敗があっても、少なくとも引数解析そのものでは落ちにくくなっています。\n\n## dry-run について\n\n`--dry-run` では通信を行わず、現在使用される設定だけを表示します。\n\n```sh\nuv run nes_recycle --dry-run\n```\n","parser_metrics":{"tags":0,"mismatched_tags":0}}}