Proxmox上にUbuntuの仮想マシンを作成し、インターネットに接続できる状態にします。これにより、外部からのアクセスや必要なパッケージのインストールが可能となります。
UbuntuサーバーにPythonや関連パッケージをインストールします。以下のコマンドを使用してください。
sudo apt update
sudo apt install -y python3 python3-pip python3-venv
Pythonの仮想環境を作成し、アクティベートします。これにより、プロジェクトごとに依存関係を管理できます。
python3 -m venv venv
source venv/bin/activate
FastAPIやLINE BOT SDK、Notionクライアントなどの必要なパッケージをインストールします。
pip install fastapi uvicorn line-bot-sdk python-dotenv notion-client requests
Cloudflareのアカウントを作成し、既存のドメインをCloudflareに追加します。ドメインがない場合は新規取得も検討してください。
Cloudflare Tunnelを利用するために、`cloudflared`をインストールします。
wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb
Cloudflare Tunnelを作成し、トンネルIDを取得します。
cloudflared tunnel create line-bot-tunnel
作成したトンネルを設定するために、設定ファイルを作成します。以下はサンプル設定です。
tunnel: YOUR_TUNNEL_ID
credentials-file: /root/.cloudflared/YOUR_TUNNEL_ID.json
ingress:
- hostname: your-domain.com
service: http://localhost:8000
- service: http_status:404
設定ファイルを基にトンネルを起動します。
sudo cloudflared tunnel --config /etc/cloudflared/config.yml run line-bot-tunnel
LINE Developers Consoleにログインし、新しいプロバイダーとチャネルを作成します。チャネル作成後、チャネルアクセストークンとチャネルシークレットを取得します。
Webhook URLとして、Cloudflare Tunnelで設定したURL(例: https://your-domain.com/webhook)をLINE Developers Consoleに設定します。
プロジェクトディレクトリを以下のように構造化します。
linebot_project/
├── main.py
├── .env
└── services/
├── line_service.py
└── notion_service.py
環境変数を管理するために、`.env`ファイルを作成し、以下の内容を記述します。
LINE_CHANNEL_SECRET=your_line_channel_secret
LINE_CHANNEL_ACCESS_TOKEN=your_line_channel_access_token
NOTION_API_KEY=your_notion_api_key
NOTION_DATABASE_ID=your_notion_database_id
`services/line_service.py`を作成し、LINE BOTの基本設定を行います。
import os
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage
class LineService:
def __init__(self):
self.line_bot_api = LineBotApi(os.getenv('LINE_CHANNEL_ACCESS_TOKEN'))
self.handler = WebhookHandler(os.getenv('LINE_CHANNEL_SECRET'))
def validate_signature(self, body, signature):
try:
self.handler.handle(body, signature)
return True
except InvalidSignatureError:
return False
`services/notion_service.py`を作成し、Notion APIとの連携を設定します。
import os
from notion_client import Client
from datetime import datetime
class NotionService:
def __init__(self):
self.notion = Client(auth=os.getenv('NOTION_API_KEY'))
self.database_id = os.getenv('NOTION_DATABASE_ID')
def create_diary_entry(self, text):
today = datetime.now().strftime("%Y-%m-%d")
try:
self.notion.pages.create(
parent={"database_id": self.database_id},
properties={
"Date": {"date": {"start": today}},
"Content": {"rich_text": [{"text": {"content": text}}]}
}
)
return True
except Exception as e:
print(f"Notion error: {e}")
return False
`main.py`を作成し、FastAPIアプリケーションを設定します。
from fastapi import FastAPI, Request, Header, HTTPException
from dotenv import load_dotenv
from services.line_service import LineService
from services.notion_service import NotionService
from linebot.models import TextSendMessage
load_dotenv()
app = FastAPI()
line_service = LineService()
notion_service = NotionService()
@app.post("/webhook")
async def line_webhook(request: Request, x_line_signature: str = Header(None)):
body = await request.body()
body_str = body.decode('utf-8')
if not line_service.validate_signature(body_str, x_line_signature):
raise HTTPException(status_code=400, detail="Invalid signature")
events = line_service.handler.parser.parse(body_str)
for event in events:
if isinstance(event.message, TextMessage):
text = event.message.text
if notion_service.create_diary_entry(text):
line_service.line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="日記を保存しました!")
)
else:
line_service.line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="日記の保存に失敗しました。")
)
return {"message": "OK"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
ユーザーが初回にアクセストークンを入力できるように、トークン設定用のエンドポイントを追加します。
@app.post("/set_tokens")
async def set_tokens(payload: dict):
"""
JSON形式の例:
{
"line": "YOUR_LINE_ACCESS_TOKEN",
"notion": "YOUR_NOTION_API_KEY"
}
"""
if "notion" in payload:
notion_service.notion = Client(auth=payload["notion"])
if "line" in payload:
line_service.line_bot_api = LineBotApi(payload["line"])
return {"message": "アクセストークンが設定されました。", "current_tokens": payload}
アクセストークンは環境変数や安全なストレージに保存し、不正アクセスを防ぐために適切に管理します。
Notionで日記を保存するためのデータベースを作成し、各日付ごとにページを作成します。各ページには日記の内容が追加されていきます。
作成したNotionデータベースのIDを取得し、`.env`ファイルに設定します。
以下のコマンドでFastAPIサーバーを起動します。
uvicorn main:app --host 0.0.0.0 --port 8000
Cloudflare Tunnelを起動して、外部からのアクセスを可能にします。
sudo cloudflared tunnel --config /etc/cloudflared/config.yml run line-bot-tunnel
LINEアプリからBOTにメッセージを送信し、Notionデータベースに日記が正しく記録されることを確認します。
ディレクトリ/ファイル | 説明 |
---|---|
linebot_project/ | プロジェクトのルートディレクトリ |
├── main.py | FastAPIアプリケーションのメインファイル |
├── .env | 環境変数を格納するファイル |
└── services/ | サービス関連のモジュールを格納するディレクトリ |
├── line_service.py | LINE BOTのサービスロジック |
└── notion_service.py | Notion APIとの連携ロジック |
本ガイドでは、PythonとFastAPIを使用してLINE公式BOTを構築し、Cloudflare Tunnelを介して自宅サーバーから外部アクセスを可能にする方法を詳述しました。BOTはユーザーから受け取った日記メッセージをNotionデータベースに自動的に記録します。これにより、ポート開放を行わずに安全かつ効率的にサービスを提供できます。セキュリティ対策やエラーハンドリングを強化することで、さらに信頼性の高いシステムを構築することが可能です。