# Line Bot 教學 ## 簡介 ### 什麼是 Line Bot? Line Bot 是一個運行在 Line 這個即時通訊平台上的應用程式。它透過 Line 提供的 API (應用程式介面) 與使用者進行互動,可以自動回覆訊息、提供資訊、執行特定功能,甚至串接其他服務。 :::info 你知道嗎? Line Bot 就是啟用Messaging API的官方帳號 像有些老師與家長溝通的帳號、商家的帳號(例如麥當勞...) 啟用Messaging API的官方帳號就可以透過程式自動回覆發送訊息 ::: ### Line Bot 的主要功能: * **自動回覆訊息:** 根據使用者輸入的文字、貼圖、圖片等內容,自動發送預先設定的回覆。 * **推播訊息:** 主動向使用者發送通知、提醒或促銷訊息。 * **提供資訊:** 可以查詢天氣、新聞、股價、交通資訊等各種即時資訊。 * **執行特定功能:** 例如預訂餐廳、查詢商品等。 * **串接外部服務:** 可以與其他服務、應用程式或資料庫整合,提供更豐富的功能。 ### 開發 Line Bot 的優點: * **龐大的用戶基礎:** Line 在許多國家和地區擁有廣大的用戶群。 * **多樣化的互動方式:** 支援文字、圖片、影片、聲音、貼圖、位置資訊等多種訊息格式。 * **豐富的 API 功能:** 提供開發者許多工具來打造功能強大的機器人。 * **提升品牌形象:** 可以作為企業與顧客互動的新管道,提供更便捷的服務。 ## Line Bot Python 簡介 Line Bot 是一種在 Line 這個通訊軟體上運行的應用程式。透過 Line Bot,使用者可以與之互動,獲取資訊、執行指令、甚至進行更複雜的操作。而使用 Python 語言開發 Line Bot,則能利用 Python 豐富的函式庫和簡潔的語法,快速打造功能強大的聊天機器人。 **運作原理:** 1. **使用者互動:** 當 Line 的使用者傳送訊息給你的 Line Bot 時,Line 的伺服器會接收到這個訊息。 2. **訊息傳遞:** Line 伺服器會將這個訊息以 HTTPS POST 的方式傳送至你事先設定好的 Webhook URL。這個 URL 指向你的伺服器或雲端服務,上面運行著你的 Python Line Bot 程式。 3. **伺服器處理:** 你的 Python 程式接收到這個 HTTP POST 請求,並解析其中的訊息內容(例如:文字、圖片、貼圖等)。 4. **邏輯處理:** 根據接收到的訊息,你的 Python 程式會執行預先定義好的邏輯。這可能包括查詢資料庫、呼叫外部 API、進行自然語言處理等等。 5. **訊息回傳:** 你的 Python 程式會根據處理結果,建構要回覆給使用者的訊息。這些訊息可以是文字、圖片、影片、按鈕、輪播等不同格式。 6. **訊息傳送:** 你的伺服器會將建構好的回覆訊息以 HTTPS POST 的方式傳送回 Line 的伺服器。 7. **使用者接收:** Line 的伺服器接收到回覆訊息後,會將其傳送給發送訊息的使用者,使用者就能在 Line 的聊天視窗中看到 Bot 的回覆。 **Python 的優勢:** * **易學易用:** Python 語法簡潔清晰,非常適合初學者入門。 * **豐富的函式庫:** Python 社群提供了許多用於網路請求、JSON 處理、資料庫操作等方面的函式庫,能大幅簡化開發流程。 * **Line Bot SDK:** Line 官方提供了 Python SDK,封裝了與 Line Bot API 互動的細節,讓開發者能更方便地處理訊息接收、回覆、以及其他進階功能。 * **廣泛的應用場景:** 使用 Python 開發的 Line Bot 可以應用於各種場景,例如:客服、通知、娛樂、資訊查詢、自動化流程等等。 使用 Python 開發 Line Bot 是一個快速且有效率的方式,讓你能夠輕鬆地在 Line 這個廣受歡迎的平台上打造智能化的互動應用。 ## 程式編寫 為了簡化環境的安裝 我們使用[Firebase Studio](https://studio.firebase.google.com)進行開發 ### 環境安裝 首先使用Google帳號登入[Firebase Studio](https://studio.firebase.google.com) 進入畫面後,在左下角找到**New Workspace** ![螢幕擷取畫面 2025-04-23 134221](https://hackmd.io/_uploads/HkSAC-vJgx.png) 接著會進入範本庫,在下方找到**backend(後端)** 在右邊找到並點擊**Python Flask**圖塊 ![螢幕擷取畫面 2025-04-23 134317](https://hackmd.io/_uploads/HJAlkGDJge.png) 在頁面跳轉後輸入**Line Bot**當作專案名稱,並按下**creat** ![螢幕擷取畫面 2025-04-23 134354](https://hackmd.io/_uploads/HywGJMvJel.png) :::info 其他選項皆使用預設即可,不需要更改 ::: 接著等待工作區建立,並同意服務條款 ![螢幕擷取畫面 2025-04-23 134503](https://hackmd.io/_uploads/By1IBGDkxl.png) 工作區建立完成後會看到VS Code的介面 ![螢幕擷取畫面 2025-04-23 134553](https://hackmd.io/_uploads/By58SfP1le.png) 把其他檔案全部刪光光(不要怕!!!)以及調整一些自己習慣的設定 再來建立名為**bot.py的檔案**以及**localtunnel.txt** ![螢幕擷取畫面 2025-04-23 135713](https://hackmd.io/_uploads/BJu_SGDyge.png) ![螢幕擷取畫面 2025-04-23 135742](https://hackmd.io/_uploads/Sk3dSfDJxx.png) 好啦~可以進到下一步了! ## 機器人製作 ### 機器人申請 進入[LINE Developers](https://developers.line.biz/en/)點選啟動控制台並登入Line帳號 ![image](https://hackmd.io/_uploads/BkcYGMIkll.png) 登入並進入控制台後點擊綠色的**Creat**按鈕輸入**bot**當作provider的名稱 ![image](https://hackmd.io/_uploads/B1H_VfLyex.png) 點擊下方上一步設置的**provider** ![image](https://hackmd.io/_uploads/rk7sNfU1ee.png) 點擊下方的**Create a new channel**大框框 ![image](https://hackmd.io/_uploads/H1y2NzUJxg.png) 在彈窗中選擇**Messaging API** ![image](https://hackmd.io/_uploads/SkHaNG81xg.png) 點擊綠按鈕跳轉到[官方帳號申請頁面](https://entry.line.biz/form/entry/unverified) :::success 跳轉前的頁面可以先留著不要關掉喔!(頁面一) ::: ![image](https://hackmd.io/_uploads/Byu04GIkex.png) 輸入你的機器人名稱及電子郵件等資訊 然後點擊確定 ![image](https://hackmd.io/_uploads/ry9vIfLyll.png) 點擊綠色的**完成**按鈕 ![image](https://hackmd.io/_uploads/SyYxwM8Jxe.png) 點擊綠色的**稍後進行認證**按鈕 ![image](https://hackmd.io/_uploads/H1-fwz8yll.png) 進入管理頁面後 可以把一些同意及教學點掉 再來點選右上角的設定按鈕 ![image](https://hackmd.io/_uploads/SycA_fUylg.png) 在左邊切換到Message API分頁 點擊**啟用Message API**按鈕 ![image](https://hackmd.io/_uploads/BkJgKzL1ge.png) 選擇先前設置的provider ![image](https://hackmd.io/_uploads/rk2btG8yxl.png) 輸入隱私權政策與服務條款 :::info 此部分可以跳過,可以直接點擊確定即可 ::: ![image](https://hackmd.io/_uploads/SkJ7Yf8kxe.png) 再次確認一下資訊,點擊確定 ![image](https://hackmd.io/_uploads/HyE7KzIkex.png) 接著就會看到這個有輸入框的介面 等待程式編寫完後會填上Webhook網址 ![image](https://hackmd.io/_uploads/SyZ8tGIJxg.png) :::success 這個頁面可以先留著不要關掉喔!(頁面二) 讓我們來寫程式吧! ::: ### 函式庫安裝 點選左上角的3條線>>點選**Terminal**>>點選**New Terminal** ![image](https://hackmd.io/_uploads/B1TqxG8kxe.png) 將底下的指令輸入終端機 ```cmd= python -m venv .venv source .venv/bin/activate pip install Flask pip install line-bot-sdk pip install google-genai pip install pillow ``` ![image](https://hackmd.io/_uploads/SJS4xdilgg.png) ### 程式編寫 寫機器人當然要先從echo Bot開始啦! 回到...左邊的檔案櫃打開先前建立的**bot.py**檔案並貼上以下內容⬇️ ```py= from flask import Flask, request, abort # 載入 LINE Message API 相關函式庫 from linebot.v3.webhook import WebhookHandler from linebot.v3.exceptions import InvalidSignatureError from linebot.v3.messaging import ( Configuration, ApiClient, MessagingApi, ReplyMessageRequest, TextMessage as V3TextMessage ) from linebot.v3.webhooks import MessageEvent, TextMessageContent # 請填入你的 Channel Access Token 與 Channel Secret CHANNEL_ACCESS_TOKEN = 'YOUR_CHANNEL_ACCESS_TOKEN' CHANNEL_SECRET = 'YOUR_CHANNEL_SECRET' app = Flask(__name__) # 初始化 LINE Bot API 配置 configuration = Configuration(access_token=CHANNEL_ACCESS_TOKEN) api_client = ApiClient(configuration) line_bot_api = MessagingApi(api_client) handler = WebhookHandler(CHANNEL_SECRET) @app.route("/callback", methods=['POST']) def callback(): signature = request.headers.get('X-Line-Signature') body = request.get_data(as_text=True) app.logger.info("Request body: " + body) try: handler.handle(body, signature) except InvalidSignatureError: app.logger.info("Invalid signature. Please check your channel access token/channel secret.") abort(400) return 'OK' @handler.add(MessageEvent, message=TextMessageContent) def handle_message(event): # 取得使用者傳送的文字訊息 received_text = event.message.text # 回覆的文字訊息,直接 echo 用戶發送的訊息 reply_text = f"你說:{received_text}" # 使用 LINE Bot API 回覆 with ApiClient(configuration) as api_client: line_bot_api = MessagingApi(api_client) line_bot_api.reply_message_with_http_info( ReplyMessageRequest( reply_token=event.reply_token, messages=[V3TextMessage(text=reply_text)] ) ) if __name__ == "__main__": app.run(debug=True, host="0.0.0.0", port=8080) ``` #### 密鑰填寫 接著回到[Line控制台](https://developers.line.biz/console/)(頁面一) 找到你的機器人點進去進到**Basic settings**分頁 往下滑動找到**Channel secret**並複製到程式碼中 ![image](https://hackmd.io/_uploads/HJa29f81lg.png) 回到上方在**Basic settings**的右邊找到**Messaging API**分頁往下滑動找到**Channel access token** 點擊**Issue**並將產生的金鑰複製到程式碼中 ![image](https://hackmd.io/_uploads/BJDdozU1gl.png) ## 內網穿透 因為Line Message API要求使用Webhook以及HTTPS,所以我們在內網環境時需要使用內網穿透解決沒有公網IP的問題,順便解決HTTPS 我們可以使用[localtunnel](https://theboroer.github.io/localtunnel-www/)的服務進行內網穿透 一樣點選左上角的3條線>>點選**Terminal**>>點選**New Terminal** 將以下指令輸入終端機執行 此指令將會安裝內網穿透服務 ```cmd= npm install -g localtunnel ``` ![image](https://hackmd.io/_uploads/S1nDFwjxel.png) 等待安裝完畢後 ![image](https://hackmd.io/_uploads/SkY9KPjxlx.png) 想一個不容易被別人使用的子網域名 例如我是用**westernpenguin** 則開通內網穿透的指令長這樣 記得把指令複製到**localtunnel.txt**下次啟動通道比較方便 ```cmd= lt --port 8080 -s westernpenguin ``` ![image](https://hackmd.io/_uploads/S1sTKDjgxe.png) 接著等待跳出網址 將終端機中顯示網址複製並在後面貼上**/callback** :::info 例如: https://westernpenguin.loca.lt/callback ::: 並貼上到先前建立好官方帳號時可以填入Webhook連結的地方(頁面二) :::info 如果你想架Minecraft 伺服器也可以用這個內網穿透服務喔! ::: ### 測試 打開Line傳送訊息給你的機器人吧! 如果如果如果沒問題應該就會自動回覆你 ![image](https://hackmd.io/_uploads/Hy5SSdogex.png) :::warning 欸?為什麼會先顯示不能個別回覆的訊息 這是因為Line預設一些訊息回覆 等等後面會有移除預設回覆的教學喔! ::: ## AI回覆 因為Line 機器人太廢了,~~除了使用者多就沒優點了~~ 所以只好串接Google 的 Gemini進行人工智慧對話 :::info 為什麼不用Chat GPT的服務呢? 因為Chat GPT提供的免費額度是有限的,而 Google 的免費服務提供在1分鐘內60次的提問 ::: 首先,使用Google個人帳戶登入[Google AI Studio](https://aistudio.google.com/app/apikey)獲得金鑰 點藍色按鈕在彈窗中隨便選一個專案 接著就會跳出金鑰了 ![image](https://hackmd.io/_uploads/H1bwT_oleg.png) ![image](https://hackmd.io/_uploads/r1_Ta_ilee.png) 接著替換全部程式碼⬇️(記得將api_key及機器人金鑰替換成你自己的) ```python= from flask import Flask, request, abort # 載入 LINE Message API 相關函式庫 from linebot.v3.webhook import WebhookHandler from linebot.v3.exceptions import InvalidSignatureError from linebot.v3.messaging import ( Configuration, ApiClient, MessagingApi, ReplyMessageRequest, TextMessage as V3TextMessage ) from linebot.v3.webhooks import MessageEvent, TextMessageContent, ImageMessageContent from google import genai from google.genai import types from PIL import Image import requests from collections import defaultdict import json import os # 新增 os 模組 import tempfile # 新增 tempfile 模組 # 請填入你的 Channel Access Token 與 Channel Secret CHANNEL_ACCESS_TOKEN = 'YOUR_CHANNEL_ACCESS_TOKEN' CHANNEL_SECRET = 'YOUR_CHANNEL_SECRET' # 儲存圖片的目錄 SAVE_IMAGE_PATH = "saved_images" if not os.path.exists(SAVE_IMAGE_PATH): os.makedirs(SAVE_IMAGE_PATH) # 初始化 Google GenAI 客戶端 client = genai.Client(api_key="YOUR_api_key") model_name = "gemini-2.0-flash" # 啟用聯網搜尋工具 tools = [types.Tool(google_search=types.GoogleSearch())] generate_content_config = types.GenerateContentConfig( temperature=0.7, top_p=1, top_k=1, max_output_tokens=1500, tools=tools, response_mime_type="text/plain", system_instruction=( "你是一個智慧型的LINE聊天機器人,請用繁體中文回答問題。" "如果有人問你是誰,請回答你的名字叫'西極企鵝',並加上一些自我介紹。" "盡量適當地用表情符號表達情緒" "因為Line 不支援Markdown" "所以請使用emoji 表示順序等資訊增加可讀性" ) ) # 儲存對話記錄 chat_sessions = defaultdict(list) app = Flask(__name__) # 初始化 LINE Bot API 配置 configuration = Configuration(access_token=CHANNEL_ACCESS_TOKEN) api_client = ApiClient(configuration) line_bot_api = MessagingApi(api_client) handler = WebhookHandler(CHANNEL_SECRET) @app.route("/callback", methods=['POST']) # 修正路由 URL def callback(): signature = request.headers['X-Line-Signature'] body = request.get_data(as_text=True) app.logger.info("Request body: " + body) try: handler.handle(body, signature) except InvalidSignatureError: app.logger.info("Invalid signature. Please check your channel access token/channel secret.") abort(400) return 'OK' @handler.add(MessageEvent, message=TextMessageContent) def handle_message(event): user_id = event.source.user_id if user_id not in chat_sessions: chat_sessions[user_id] = client.chats.create(model=model_name, config=generate_content_config) chat = chat_sessions[user_id] msg = event.message.text print(f"Received message: {msg}") # 使用 Google GenAI 生成回覆 response = chat.send_message(message=msg) reply = response.text with ApiClient(configuration) as api_client: line_bot_api = MessagingApi(api_client) line_bot_api.reply_message_with_http_info( ReplyMessageRequest( reply_token=event.reply_token, messages=[V3TextMessage(text=reply)] ) ) @handler.add(MessageEvent, message=ImageMessageContent) def handle_image_message(event): message_id = event.message.id try: # 使用 requests 從 LINE API 下載圖片內容 content_url = f"https://api-data.line.me/v2/bot/message/{message_id}/content" headers = {"Authorization": f"Bearer {CHANNEL_ACCESS_TOKEN}"} response = requests.get(content_url, headers=headers, stream=True) if response.status_code == 200: # 使用 PIL.Image.open 處理圖片數據 image = Image.open(response.raw) # 傳遞圖片和文字訊息給 Gemini 處理 user_id = event.source.user_id if user_id not in chat_sessions: chat_sessions[user_id] = client.chats.create(model=model_name, config=generate_content_config) chat = chat_sessions[user_id] message_text = "這是一張圖片,請分析並生成相關內容。" response = client.models.generate_content( model="gemini-2.0-flash", contents=[image, message_text], config=generate_content_config ) response = chat.send_message(f"Image processed: {response.text}", config=generate_content_config) # 修正參數傳遞 reply_text = f"{response.text}\n" else: reply_text = f"無法下載圖片,狀態碼: {response.status_code}" except Exception as e: reply_text = f"處理圖片時發生錯誤: {e}" line_bot_api.reply_message_with_http_info( ReplyMessageRequest( reply_token=event.reply_token, messages=[V3TextMessage(text=reply_text)] ) ) if __name__ == "__main__": app.run(debug=True, host="0.0.0.0", port=8080) ``` ### 測試 打開Line傳送訊息給你的機器人吧! 如果如果如果沒問題應該就會自動回覆你一些由生成的文字 ![image](https://hackmd.io/_uploads/rJewKdilex.png) :::warning 對!那個可惡的訊息又出現了 下一段就來教怎麼移除預設回覆 ::: ## 移除預設回覆 [LINE 官方帳號管理頁面](https://manager.line.biz/)是一個管理官方帳號的控制台 進入並挑選你的機器人 在左邊找到**自動回應訊息** ![image](https://hackmd.io/_uploads/SyA95_olxg.png) 在右邊找到訊息後點那3個點選擇刪除 ![image](https://hackmd.io/_uploads/ryS1juoggl.png) 接著應該就不會出現那個討厭的回覆了 :::info 相反的,你也可以透過它建立一些自動回覆 ::: ## 結尾 謝謝大家聆聽我的Line Bot教學課程 因為課程時間較短,內容沒有很詳細 這份講義會慢慢補齊,如果有問題也可以在群組詢問我 謝謝