# 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**

接著會進入範本庫,在下方找到**backend(後端)**
在右邊找到並點擊**Python Flask**圖塊

在頁面跳轉後輸入**Line Bot**當作專案名稱,並按下**creat**

:::info
其他選項皆使用預設即可,不需要更改
:::
接著等待工作區建立,並同意服務條款

工作區建立完成後會看到VS Code的介面

把其他檔案全部刪光光(不要怕!!!)以及調整一些自己習慣的設定
再來建立名為**bot.py的檔案**以及**localtunnel.txt**


好啦~可以進到下一步了!
## 機器人製作
### 機器人申請
進入[LINE Developers](https://developers.line.biz/en/)點選啟動控制台並登入Line帳號

登入並進入控制台後點擊綠色的**Creat**按鈕輸入**bot**當作provider的名稱

點擊下方上一步設置的**provider**

點擊下方的**Create a new channel**大框框

在彈窗中選擇**Messaging API**

點擊綠按鈕跳轉到[官方帳號申請頁面](https://entry.line.biz/form/entry/unverified)
:::success
跳轉前的頁面可以先留著不要關掉喔!(頁面一)
:::

輸入你的機器人名稱及電子郵件等資訊
然後點擊確定

點擊綠色的**完成**按鈕

點擊綠色的**稍後進行認證**按鈕

進入管理頁面後
可以把一些同意及教學點掉
再來點選右上角的設定按鈕

在左邊切換到Message API分頁
點擊**啟用Message API**按鈕

選擇先前設置的provider

輸入隱私權政策與服務條款
:::info
此部分可以跳過,可以直接點擊確定即可
:::

再次確認一下資訊,點擊確定

接著就會看到這個有輸入框的介面
等待程式編寫完後會填上Webhook網址

:::success
這個頁面可以先留著不要關掉喔!(頁面二)
讓我們來寫程式吧!
:::
### 函式庫安裝
點選左上角的3條線>>點選**Terminal**>>點選**New Terminal**

將底下的指令輸入終端機
```cmd=
python -m venv .venv
source .venv/bin/activate
pip install Flask
pip install line-bot-sdk
pip install google-genai
pip install pillow
```

### 程式編寫
寫機器人當然要先從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**並複製到程式碼中

回到上方在**Basic settings**的右邊找到**Messaging API**分頁往下滑動找到**Channel access token**
點擊**Issue**並將產生的金鑰複製到程式碼中

## 內網穿透
因為Line Message API要求使用Webhook以及HTTPS,所以我們在內網環境時需要使用內網穿透解決沒有公網IP的問題,順便解決HTTPS
我們可以使用[localtunnel](https://theboroer.github.io/localtunnel-www/)的服務進行內網穿透
一樣點選左上角的3條線>>點選**Terminal**>>點選**New Terminal**
將以下指令輸入終端機執行
此指令將會安裝內網穿透服務
```cmd=
npm install -g localtunnel
```

等待安裝完畢後

想一個不容易被別人使用的子網域名
例如我是用**westernpenguin**
則開通內網穿透的指令長這樣
記得把指令複製到**localtunnel.txt**下次啟動通道比較方便
```cmd=
lt --port 8080 -s westernpenguin
```

接著等待跳出網址
將終端機中顯示網址複製並在後面貼上**/callback**
:::info
例如:
https://westernpenguin.loca.lt/callback
:::
並貼上到先前建立好官方帳號時可以填入Webhook連結的地方(頁面二)
:::info
如果你想架Minecraft 伺服器也可以用這個內網穿透服務喔!
:::
### 測試
打開Line傳送訊息給你的機器人吧!
如果如果如果沒問題應該就會自動回覆你

:::warning
欸?為什麼會先顯示不能個別回覆的訊息
這是因為Line預設一些訊息回覆
等等後面會有移除預設回覆的教學喔!
:::
## AI回覆
因為Line 機器人太廢了,~~除了使用者多就沒優點了~~
所以只好串接Google 的 Gemini進行人工智慧對話
:::info
為什麼不用Chat GPT的服務呢?
因為Chat GPT提供的免費額度是有限的,而 Google 的免費服務提供在1分鐘內60次的提問
:::
首先,使用Google個人帳戶登入[Google AI Studio](https://aistudio.google.com/app/apikey)獲得金鑰
點藍色按鈕在彈窗中隨便選一個專案
接著就會跳出金鑰了


接著替換全部程式碼⬇️(記得將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傳送訊息給你的機器人吧!
如果如果如果沒問題應該就會自動回覆你一些由生成的文字

:::warning
對!那個可惡的訊息又出現了
下一段就來教怎麼移除預設回覆
:::
## 移除預設回覆
[LINE 官方帳號管理頁面](https://manager.line.biz/)是一個管理官方帳號的控制台
進入並挑選你的機器人
在左邊找到**自動回應訊息**

在右邊找到訊息後點那3個點選擇刪除

接著應該就不會出現那個討厭的回覆了
:::info
相反的,你也可以透過它建立一些自動回覆
:::
## 結尾
謝謝大家聆聽我的Line Bot教學課程
因為課程時間較短,內容沒有很詳細
這份講義會慢慢補齊,如果有問題也可以在群組詢問我
謝謝