Nai-Yun commited on
Commit
14dcd88
·
verified ·
1 Parent(s): 001eb32

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -58
app.py CHANGED
@@ -19,14 +19,14 @@ model = genai.GenerativeModel('gemini-2.5-flash')
19
  # 建立我們的虛擬藥妝資料庫 (Mock Database)
20
  fake_database = {
21
  "CeraVe適樂膚 長效潤澤修護霜 340g": [
22
- {"store": "屈臣氏", "name": "CeraVe適樂膚 長效潤澤修護霜 340g", "price": "619","link": "https://www.watsons.com.tw/cerave-cerave%E9%81%A9%E6%A8%82%E8%86%9A%E9%95%B7%E6%95%88%E6%BD%A4%E6%BE%A4%E4%BF%AE%E8%AD%B7%E9%9C%9C-340g/p/BP_153671"},
23
- {"store": "康是美", "name": "CeraVe適樂膚 長效潤澤修護霜 340g", "price": "619", "link": "https://shop.cosmed.com.tw/SalePage/Index/6414249"},
24
- {"store": "寶雅", "name": "CeraVe適樂膚 長效潤澤修護霜 340g", "price": "619","link": "https://www.poyabuy.com.tw/SalePage/Index/10104261"}
25
  ],
26
  "Avene 雅漾舒護活泉水150ml": [
27
- {"store": "屈臣氏", "name": "Avene 雅漾舒護活泉水150ml", "price": "299","discount": "🔥限時67折", "link": "https://www.watsons.com.tw/avene-%E9%9B%85%E6%BC%BE-%E9%9B%85%E6%BC%BE%E8%88%92%E8%AD%B7%E6%B4%BB%E6%B3%89%E6%B0%B4150ml/p/BP_291419"},
28
- {"store": "康是美", "name": "Avene 雅漾舒護活泉水150ml", "price": "299","discount": "🔥限時67折", "link": "https://shop.cosmed.com.tw/SalePage/Index/5767522"},
29
- {"store": "寶雅", "name": "Avene 雅漾舒護活泉水150ml", "price": "450", "link": "https://www.poyabuy.com.tw/SalePage/Index/9929185"}
30
  ]
31
  }
32
 
@@ -109,81 +109,90 @@ def handle_image(event):
109
 
110
  # --- 第 4 步:將資料塞進橫向圖卡 (不管哪條路線,最後都會來到這裡) ---
111
  # --- 第 4 步:將資料塞進橫向圖卡 ---
 
 
112
  bubbles = []
113
  for item in data_list:
114
 
115
- # --- 這裡用來判斷要不要顯示折扣標籤 ---
116
- discount_box = []
117
- # 只有當資料庫裡的 discount 不是空字串時,才生出這塊紅色的標籤
118
- if item.get("discount"):
119
- discount_box = [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  {
121
  "type": "box",
122
- "layout": "baseline",
123
- "spacing": "sm",
124
  "contents": [
125
- {
126
- "type": "text",
127
- "text": item["discount"],
128
- "color": "#ffffff",
129
- "size": "xs",
130
- "weight": "bold",
131
- "margin": "sm"
132
- }
133
- ],
134
- "backgroundColor": "#ff3b30", # 紅色底
135
- "cornerRadius": "md",
136
- "paddingAll": "2px",
137
- "paddingStart": "8px",
138
- "paddingEnd": "8px",
139
- "margin": "sm"
140
  }
141
  ]
 
142
 
143
- # 這是原本卡片的身體內容,我們把剛剛可能生出來的折扣標籤塞進去
144
- card_contents = [
145
- {"type": "text", "text": item["store"], "weight": "bold", "color": "#1DB446", "size": "md"},
146
- {"type": "text", "text": item["name"], "weight": "bold", "size": "lg", "margin": "md", "wrap": True},
147
- ]
148
-
149
- # 把折扣標籤接在商品名稱後面
150
- card_contents.extend(discount_box)
151
-
152
- # 補上最後的價格線
153
- card_contents.extend([
154
- {"type": "separator", "margin": "lg"},
155
- {
156
- "type": "box",
157
- "layout": "horizontal",
158
- "margin": "md",
159
- "contents": [
160
- {"type": "text", "text": price_tag, "size": "sm", "color": "#555555"},
161
- {"type": "text", "text": f"${item['price']}", "size": "lg", "color": "#111111", "align": "end", "weight": "bold"}
162
- ]
163
- }
164
- ])
165
-
166
- # 組裝最終的卡片
167
  card = {
168
  "type": "bubble",
 
 
 
 
 
 
 
 
 
169
  "body": {
170
  "type": "box",
171
  "layout": "vertical",
172
- "contents": card_contents
 
 
 
 
 
173
  },
174
  "footer": {
175
  "type": "box",
176
  "layout": "vertical",
177
  "contents": [
 
178
  {
179
  "type": "button",
180
  "style": "primary",
181
- "color": "#1DB446",
182
- "height": "sm",
183
  "action": {
184
  "type": "uri",
185
  "label": "前往商家購買",
186
- # 這裡改用資料庫裡設定的專屬網址��(如果沒設定,就預設用 Google 搜尋)
187
  "uri": item.get("link", f"https://www.google.com/search?q={item['store']}+{item['name']}")
188
  }
189
  }
@@ -191,6 +200,7 @@ def handle_image(event):
191
  }
192
  }
193
  bubbles.append(card)
 
194
 
195
  # --- 第 5 步:打包發送圖卡 ---
196
  flex_message = FlexSendMessage.new_from_json_dict({
@@ -201,16 +211,17 @@ def handle_image(event):
201
  "contents": bubbles
202
  }
203
  })
204
-
205
  line_bot_api.push_message(user_id, flex_message)
206
  del user_states[user_id]
207
-
208
  except Exception as e:
209
  line_bot_api.push_message(
210
  user_id,
211
  TextSendMessage(text=f"❌ 哎呀!精靈遇到了一點問題。錯誤原因:\n{e}")
212
  )
213
 
 
 
 
214
  # ================= 3. 多輪對話核心邏輯 =================
215
  @handler.add(MessageEvent, message=TextMessage)
216
  def handle_message(event):
 
19
  # 建立我們的虛擬藥妝資料庫 (Mock Database)
20
  fake_database = {
21
  "CeraVe適樂膚 長效潤澤修護霜 340g": [
22
+ {"store": "屈臣氏", "name": "CeraVe適樂膚 長效潤澤修護霜 340g", "price": "619","link": "https://www.watsons.com.tw/cerave-cerave%E9%81%A9%E6%A8%82%E8%86%9A%E9%95%B7%E6%95%88%E6%BD%A4%E6%BE%A4%E4%BF%AE%E8%AD%B7%E9%9C%9C-340g/p/BP_153671","image": "https://img.91app.com/webapi/imagesV3/Original/SalePage/10104261/0/639160140536830000?v=1"},
23
+ {"store": "康是美", "name": "CeraVe適樂膚 長效潤澤修護霜 340g", "price": "619", "link": "https://shop.cosmed.com.tw/SalePage/Index/6414249","image": "https://img.91app.com/webapi/imagesV3/Original/SalePage/10104261/0/639160140536830000?v=1"},
24
+ {"store": "寶雅", "name": "CeraVe適樂膚 長效潤澤修護霜 340g", "price": "619","link": "https://www.poyabuy.com.tw/SalePage/Index/10104261","image": "https://img.91app.com/webapi/imagesV3/Original/SalePage/10104261/0/639160140536830000?v=1"}
25
  ],
26
  "Avene 雅漾舒護活泉水150ml": [
27
+ {"store": "屈臣氏", "name": "Avene 雅漾舒護活泉水150ml", "price": "299","discount": "🔥限時67折", "link": "https://www.watsons.com.tw/avene-%E9%9B%85%E6%BC%BE-%E9%9B%85%E6%BC%BE%E8%88%92%E8%AD%B7%E6%B4%BB%E6%B3%89%E6%B0%B4150ml/p/BP_291419","image": "https://img.91app.com/webapi/imagesV3/Original/SalePage/9929185/0/639160572853670000?v=1"},
28
+ {"store": "康是美", "name": "Avene 雅漾舒護活泉水150ml", "price": "299","discount": "🔥限時67折", "link": "https://shop.cosmed.com.tw/SalePage/Index/5767522"},"image": "https://img.91app.com/webapi/imagesV3/Original/SalePage/9929185/0/639160572853670000?v=1",
29
+ {"store": "寶雅", "name": "Avene 雅漾舒護活泉水150ml", "price": "450", "link": "https://www.poyabuy.com.tw/SalePage/Index/9929185","image": "https://img.91app.com/webapi/imagesV3/Original/SalePage/9929185/0/639160572853670000?v=1"}
30
  ]
31
  }
32
 
 
109
 
110
  # --- 第 4 步:將資料塞進橫向圖卡 (不管哪條路線,最後都會來到這裡) ---
111
  # --- 第 4 步:將資料塞進橫向圖卡 ---
112
+ # --- 第 4 步:將資料塞進 Toyota 風格的旗艦版圖卡 ---
113
+ # --- 第 4 步:將資料塞進 Toyota 風格的旗艦版圖卡 ---
114
  bubbles = []
115
  for item in data_list:
116
 
117
+ # 如果是 AI 估價,可能不會有圖片,我們給一張預設的漂亮漸層圖防呆
118
+ image_url = item.get("image", "https://via.placeholder.com/600x400/eeeeee/999999?text=Image+Not+Found")
119
+
120
+ # 建立中間的「規格表」 ( Toyota 顯示全長全寬那樣)
121
+ specs_box = {
122
+ "type": "box",
123
+ "layout": "vertical",
124
+ "spacing": "sm",
125
+ "margin": "lg",
126
+ "contents": [
127
+ # 第一列:通路
128
+ {
129
+ "type": "box",
130
+ "layout": "horizontal",
131
+ "contents": [
132
+ {"type": "text", "text": "販售通路", "size": "md", "color": "#8c8c8c", "flex": 1},
133
+ {"type": "text", "text": item["store"], "size": "md", "color": "#111111", "weight": "bold", "flex": 2}
134
+ ]
135
+ },
136
+ # 第二列:價格
137
  {
138
  "type": "box",
139
+ "layout": "horizontal",
 
140
  "contents": [
141
+ {"type": "text", "text": price_tag, "size": "md", "color": "#8c8c8c", "flex": 1},
142
+ {"type": "text", "text": f"${item['price']}", "size": "md", "color": "#111111", "weight": "bold", "flex": 2}
143
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
144
  }
145
  ]
146
+ }
147
 
148
+ # 如果有折扣,完美融入規格表的第三列
149
+ if item.get("discount"):
150
+ specs_box["contents"].append(
151
+ {
152
+ "type": "box",
153
+ "layout": "horizontal",
154
+ "contents": [
155
+ {"type": "text", "text": "獨家優惠", "size": "md", "color": "#8c8c8c", "flex": 1},
156
+ {"type": "text", "text": item["discount"], "size": "md", "color": "#ff3b30", "weight": "bold", "flex": 2}
157
+ ]
158
+ }
159
+ )
160
+
161
+ # 組裝最終的百萬級卡片
 
 
 
 
 
 
 
 
 
 
162
  card = {
163
  "type": "bubble",
164
+ "size": "mega", # 設定跟 Toyota 一樣的寬版大卡片
165
+ "hero": {
166
+ "type": "image",
167
+ "url": image_url,
168
+ "size": "full",
169
+ "aspectRatio": "4:3", # 調整成最適合保養品展示的比例
170
+ "aspectMode": "fit", # 確保瓶身完整顯示不被裁切
171
+ "backgroundColor": "#FFFFFF"
172
+ },
173
  "body": {
174
  "type": "box",
175
  "layout": "vertical",
176
+ "contents": [
177
+ # 標題:超大粗體商品名 (像 Toyota 的 bZ4X)
178
+ {"type": "text", "text": item["name"], "weight": "bold", "size": "xl", "wrap": True},
179
+ # 塞入剛剛做好的規格表
180
+ specs_box
181
+ ]
182
  },
183
  "footer": {
184
  "type": "box",
185
  "layout": "vertical",
186
  "contents": [
187
+ # 底部黑底白字的大按鈕
188
  {
189
  "type": "button",
190
  "style": "primary",
191
+ "color": "#000000", # Toyota 經典純黑
192
+ "height": "md",
193
  "action": {
194
  "type": "uri",
195
  "label": "前往商家購買",
 
196
  "uri": item.get("link", f"https://www.google.com/search?q={item['store']}+{item['name']}")
197
  }
198
  }
 
200
  }
201
  }
202
  bubbles.append(card)
203
+
204
 
205
  # --- 第 5 步:打包發送圖卡 ---
206
  flex_message = FlexSendMessage.new_from_json_dict({
 
211
  "contents": bubbles
212
  }
213
  })
 
214
  line_bot_api.push_message(user_id, flex_message)
215
  del user_states[user_id]
 
216
  except Exception as e:
217
  line_bot_api.push_message(
218
  user_id,
219
  TextSendMessage(text=f"❌ 哎呀!精靈遇到了一點問題。錯誤原因:\n{e}")
220
  )
221
 
222
+
223
+
224
+
225
  # ================= 3. 多輪對話核心邏輯 =================
226
  @handler.add(MessageEvent, message=TextMessage)
227
  def handle_message(event):