Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@
__pycache__

# db
sql_app.db
sql_app.db

# logs
logs/
8 changes: 5 additions & 3 deletions linebot/app/api/vision.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import os
import json
import traceback
from typing import Optional, Dict, Any, List

# Import OpenAI API and image processing utilities
from .utils.openai_api import openai_api
from .utils.image_processing import encode_image
from ..config.logger import get_logger

# 取得模組的日誌記錄器
logger = get_logger(__name__)


def process_image(image_path: str, prompt: str = "圖片內容有什麼?") -> str:
Expand Down Expand Up @@ -48,5 +50,5 @@ def process_image(image_path: str, prompt: str = "圖片內容有什麼?") -> st
return reply_msg
except Exception as e:
error_detail = f"未預期的錯誤: {str(e)}\n{traceback.format_exc()}"
print(error_detail)
logger.error(error_detail)
return "處理圖片時發生錯誤,請稍後再試"
82 changes: 82 additions & 0 deletions linebot/app/config/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""
日誌管理模組 - 為應用程式提供統一的日誌處理功能
"""

import logging
import sys
import os
from logging.handlers import RotatingFileHandler

# 日誌格式
LOG_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
# 日期格式
DATE_FORMAT = "%Y-%m-%d %H:%M:%S"

# 日誌檔案路徑
LOG_DIR = "logs"
if not os.path.exists(LOG_DIR):
os.makedirs(LOG_DIR)

# 日誌等級對應表
LOG_LEVELS = {
"debug": logging.DEBUG,
"info": logging.INFO,
"warning": logging.WARNING,
"error": logging.ERROR,
"critical": logging.CRITICAL,
}

# 預設日誌等級
DEFAULT_LOG_LEVEL = "info"


def get_logger(name: str, level: str = None) -> logging.Logger:
"""
取得設定好的日誌記錄器

Args:
name: 日誌記錄器名稱,通常使用模組名稱 __name__
level: 日誌等級,可選 debug、info、warning、error、critical,預設為 info

Returns:
logging.Logger: 設定好的日誌記錄器
"""
# 如果未指定層級,使用預設的
if level is None:
level = DEFAULT_LOG_LEVEL

# 取得日誌層級
log_level = LOG_LEVELS.get(level.lower(), logging.INFO)

# 建立 logger
logger = logging.getLogger(name)
logger.setLevel(log_level)

# 禁用日誌傳播,避免重複輸出
logger.propagate = False

# 避免重複設定 handler
if not logger.handlers:
# 建立輸出到控制台的 handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(log_level)
console_formatter = logging.Formatter(LOG_FORMAT, DATE_FORMAT)
console_handler.setFormatter(console_formatter)
logger.addHandler(console_handler)

# 建立輸出到檔案的 handler
file_handler = RotatingFileHandler(
os.path.join(LOG_DIR, f"{name.split('.')[-1]}.log"),
maxBytes=10 * 1024 * 1024, # 10 MB
backupCount=5,
)
file_handler.setLevel(log_level)
file_formatter = logging.Formatter(LOG_FORMAT, DATE_FORMAT)
file_handler.setFormatter(file_formatter)
logger.addHandler(file_handler)

return logger


# 建立全域日誌記錄器
app_logger = get_logger("app")
11 changes: 8 additions & 3 deletions linebot/app/routers/linebot.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
from linebot.models import MessageEvent, TextMessage, ImageMessage, AudioMessage
from ..config.line_config import handler
from ..services.message_service import MessageService
from ..config.logger import get_logger

# 取得模組的日誌記錄器
logger = get_logger(__name__)


router = APIRouter(prefix="/linebot", tags=["linebot"])

Expand All @@ -14,21 +19,21 @@
# 註冊訊息處理函式
@handler.add(MessageEvent, message=TextMessage)
def handle_text_message(event):
print("收到文字訊息")
logger.info("收到文字訊息")
reply_messages = message_service.handle_text_message(event)
message_service.send_message(event.reply_token, reply_messages)


@handler.add(MessageEvent, message=ImageMessage)
def handle_image_message(event):
print("收到圖片訊息")
logger.info("收到圖片訊息")
reply_message = message_service.handle_image_message(event)
message_service.send_message(event.reply_token, [reply_message])


@handler.add(MessageEvent, message=AudioMessage)
def handle_audio_message(event):
print("收到音訊訊息")
logger.info("收到音訊訊息")
reply_message = message_service.handle_audio_message(event)
message_service.send_message(event.reply_token, [reply_message])

Expand Down
5 changes: 3 additions & 2 deletions linebot/app/services/handlers/audio_handler.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"""處理音訊訊息的模組"""

import logging
from linebot.models import TextSendMessage
from .common import create_quick_reply
from ...config.logger import get_logger

logger = logging.getLogger(__name__)
# 取得模組的日誌記錄器
logger = get_logger(__name__)


def handle_audio_message(event):
Expand Down
5 changes: 3 additions & 2 deletions linebot/app/services/handlers/common.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""共用函式模組"""

import logging
import requests
from linebot.models import (
QuickReply,
Expand All @@ -9,8 +8,10 @@
SendMessage,
)
from ...config.line_config import line_bot_api, LINE_CHANNEL_ACCESS_TOKEN
from ...config.logger import get_logger

logger = logging.getLogger(__name__)
# 取得模組的日誌記錄器
logger = get_logger(__name__)

# 常用指令
COMMANDS = {
Expand Down
5 changes: 3 additions & 2 deletions linebot/app/services/handlers/image_handler.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"""處理圖片訊息的模組"""

import os
import logging
from linebot.models import TextSendMessage
from .common import create_quick_reply
from ...api.vision import process_image
from ...config.line_config import line_bot_api
from ...config.logger import get_logger

logger = logging.getLogger(__name__)
# 取得模組的日誌記錄器
logger = get_logger(__name__)


def handle_image_message(event):
Expand Down
5 changes: 3 additions & 2 deletions linebot/app/services/handlers/text_handler.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"""處理文字訊息的模組"""

import json
import logging
from linebot.models import TextSendMessage, FlexSendMessage
from .common import create_quick_reply, COMMANDS
from ...api.dify import inference
from ...config.logger import get_logger

logger = logging.getLogger(__name__)
# 取得模組的日誌記錄器
logger = get_logger(__name__)


def handle_text_message(event):
Expand Down
5 changes: 3 additions & 2 deletions linebot/app/services/message_service.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
"""訊息服務模組 - 處理 LINE Bot 的各種訊息類型"""

import logging
from .handlers import (
handle_text_message,
handle_image_message,
handle_audio_message,
send_message,
show_loading_animation,
)
from ..config.logger import get_logger

logger = logging.getLogger(__name__)
# 取得模組的日誌記錄器
logger = get_logger(__name__)


# 為了保持與舊版API相容,我們可以保留這個類別作為包裝器
Expand Down
6 changes: 6 additions & 0 deletions linebot/app/webhooks/handlers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import logging
from linebot.models import MessageEvent, TextMessage, ImageMessage, AudioMessage

from ..config.line_config import handler
from ..services.message_service import MessageService
from ..config.logger import get_logger

# 取得模組的日誌記錄器
logger = get_logger(__name__)

message_service = MessageService()

Expand All @@ -17,6 +22,7 @@ def handle_message(event):
@handler.add(MessageEvent, message=ImageMessage)
def handle_image_message(event):
reply_messages = message_service.handle_image_message(event)
logger.info(f"圖片處理回應: {reply_messages}")
message_service.send_message(event.reply_token, reply_messages)


Expand Down