File size: 5,246 Bytes
cd9bca9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
"""
LINE Bot 相關工具函數
"""

from linebot.models import (
    TextSendMessage, QuickReply, QuickReplyButton, MessageAction,
    FlexSendMessage, BubbleContainer, BoxComponent, TextComponent,
    ButtonComponent, URIAction
)
from typing import List, Dict, Any
import logging

logger = logging.getLogger(__name__)

class LineMessageBuilder:
    """LINE 訊息建構器"""
    
    @staticmethod
    def create_quick_reply_message(text: str, quick_reply_items: List[Dict[str, str]]) -> TextSendMessage:
        """建立快速回覆訊息"""
        quick_reply_buttons = []
        
        for item in quick_reply_items:
            button = QuickReplyButton(
                action=MessageAction(
                    label=item["label"],
                    text=item["text"]
                )
            )
            quick_reply_buttons.append(button)
        
        quick_reply = QuickReply(items=quick_reply_buttons)
        
        return TextSendMessage(
            text=text,
            quick_reply=quick_reply
        )
    
    @staticmethod
    def create_product_flex_message(products: List[Dict[str, Any]]) -> FlexSendMessage:
        """建立商品展示的 Flex 訊息"""
        contents = []
        
        for product in products[:10]:  # 最多顯示10個商品
            bubble = BubbleContainer(
                body=BoxComponent(
                    layout="vertical",
                    contents=[
                        TextComponent(
                            text=product.get("name", "商品名稱"),
                            weight="bold",
                            size="lg"
                        ),
                        TextComponent(
                            text=f"NT$ {product.get('price', 0):,}",
                            size="md",
                            color="#ff5551"
                        ),
                        TextComponent(
                            text=f"庫存: {product.get('stock', 0)}",
                            size="sm",
                            color="#aaaaaa"
                        )
                    ]
                ),
                footer=BoxComponent(
                    layout="vertical",
                    contents=[
                        ButtonComponent(
                            action=MessageAction(
                                label="查看詳情",
                                text=f"查詢商品 {product.get('name', '')}"
                            ),
                            style="primary"
                        )
                    ]
                )
            )
            contents.append(bubble)
        
        return FlexSendMessage(
            alt_text="商品列表",
            contents={
                "type": "carousel",
                "contents": [bubble.as_json_dict() for bubble in contents]
            }
        )
    
    @staticmethod
    def create_help_message() -> TextSendMessage:
        """建立說明訊息"""
        help_text = """
🤖 歡迎使用智能查詢機器人!

📝 支援的查詢類型:
• 用戶查詢:「查詢用戶 張三」
• 訂單查詢:「查詢訂單 ORD001」
• 商品查詢:「查詢商品 iPhone」
• 價格範圍:「價格 1000 到 5000 的商品」
• 統計分析:「統計用戶數量」

💡 使用範例:
• 「找用戶名叫王小明的資料」
• 「我的訂單狀態如何」
• 「有什麼手機商品」
• 「總共有多少筆訂單」

❓ 如需協助,請輸入「幫助」或「說明」
        """
        
        quick_reply_items = [
            {"label": "查詢用戶", "text": "查詢用戶"},
            {"label": "查詢訂單", "text": "查詢訂單"},
            {"label": "查詢商品", "text": "查詢商品"},
            {"label": "統計資料", "text": "統計"}
        ]
        
        return LineMessageBuilder.create_quick_reply_message(help_text, quick_reply_items)
    
    @staticmethod
    def create_error_message(error_msg: str = None) -> TextSendMessage:
        """建立錯誤訊息"""
        default_msg = "抱歉,我無法理解您的訊息。請輸入「幫助」查看使用說明。"
        text = error_msg if error_msg else default_msg
        
        quick_reply_items = [
            {"label": "幫助", "text": "幫助"},
            {"label": "重新開始", "text": "開始"}
        ]
        
        return LineMessageBuilder.create_quick_reply_message(text, quick_reply_items)

def get_user_display_name(line_bot_api, user_id: str) -> str:
    """取得用戶顯示名稱"""
    try:
        profile = line_bot_api.get_profile(user_id)
        return profile.display_name
    except Exception as e:
        logger.error(f"取得用戶資料失敗: {str(e)}")
        return "用戶"

def validate_line_signature(body: bytes, signature: str, channel_secret: str) -> bool:
    """驗證 LINE Webhook 簽名"""
    import hashlib
    import hmac
    import base64
    
    hash_value = hmac.new(
        channel_secret.encode('utf-8'),
        body,
        hashlib.sha256
    ).digest()
    
    expected_signature = base64.b64encode(hash_value).decode('utf-8')
    return hmac.compare_digest(signature, expected_signature)