Discord Bot 開発(骨格)
関連: Discord / セットアップ / PostgreSQL
いまできること
- Discord のギルドチャンネル / DM でメッセージを受信する
- Gemini で関西弁+ちょいメンヘラ気質の返答を返す
- 支出っぽい文を抽出して PostgreSQL (
expenses) に保存(1メッセージで複数件可) - 収入も同様に記録(
incomes/create_income)。将来はメールも想定 - 画像添付(レシート・決済画面)を Vision で解析し、金額・店名・内訳・場面を推定
- 大分類 / 小分類 / occasion / 収入分類 は固定リスト(
src/finance_manager/taxonomy.py) - 会話コンテキスト: 支出・収入の訂正・削除
DISCORD_CHANNEL_ID指定時: そのギルドチャンネル + DMDISCORD_CHANNEL_ID空: 見えるギルドチャンネル全部 + DM- まだ: Tasker / IMAP(メール収入)、Calendar 連携
ディレクトリ
src/finance_manager/
__main__.py … python -m finance_manager の入口
config.py … .env 読み込み
bot.py … Discord イベント
gemini_client.py … Gemini 呼び出し
memory.py … 直近やりとり(プロセス内)
scripts/run.sh … venv + PYTHONPATH 込みの起動スクリプト
「さっきの〇〇」の仕組み
- DB からそのユーザーの直近支出(最大8件)を読む
- プロセス内の直近チャット(最大12往復)を添える
- Gemini が
action=create|update|delete|chatとtarget_expense_idを返す - update/delete は 自分の支出 id だけ 許可(他人の id は拒否)
Bot 再起動でチャット履歴は消えるが、支出一覧は DB から復元されるので「さっきのスタバ」はまだ効く。
なぜ毎回 source / export が必要か
| コマンド | 効く範囲 |
|---|---|
source .venv/bin/activate |
今のシェルだけ。新しい SSH では無効 |
export PYTHONPATH=src |
今のシェルだけ。再接続したら消える |
SSH 切断やサーバ再起動で Bot プロセスは終わる。
再接続したら、下の「再起動手順」を最初からやる。
systemd 化すると不要になる
後で systemd 常駐化すれば、手動の activate / export は不要になる。手順は systemd。
VM 上での初回セットアップ
# リポジトリを取得(初回)
cd ~
git clone https://github.com/nakajima923/finance-manager.git
cd finance-manager
# 仮想環境
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# 設定
cp .env.example .env
# .env を編集してトークン類を入れる
.env の例:
DISCORD_BOT_TOKEN=...
DISCORD_CHANNEL_ID= # 空でも可。絞るならチャンネル ID
GEMINI_API_KEY=...
GEMINI_MODEL=gemini-3.5-flash
GEMINI_MODEL_FALLBACKS=gemini-3.1-flash-lite,gemini-1.5-flash
DATABASE_URL=postgresql://finance_app:PASSWORD@127.0.0.1:5432/finance_manager
チャンネル ID の調べ方: Discord の開発者モードを ON → チャンネルを右クリック → ID をコピー
再起動手順(毎回これ)
SSH し直したあと:
cd ~/finance-manager
git pull # 更新があれば
source .venv/bin/activate # venv を有効化
export PYTHONPATH=src # finance_manager パッケージを見つけられるようにする
python -m finance_manager # Bot 起動
またはスクリプト一発:
cd ~/finance-manager
git pull # 更新があれば
chmod +x scripts/run.sh # 初回だけ
./scripts/run.sh
scripts/run.sh の中で activate と PYTHONPATH=src をやるので、忘れにくい。
成功時のログ例
Gemini model chain: gemini-3.5-flash -> ...
Logged in as ...
Listening to DMs + guild channel_id=...
DM か指定チャンネルに投稿して返答を確認する。
止める: Ctrl+C
次の実装予定
- Tasker / IMAP(Grafana 可視化は Grafana)