From 7a43c7f79e06a0be64bb5f3666b9f18b9f37f8af Mon Sep 17 00:00:00 2001 From: YiHungWONG <40423264+yihong1120@users.noreply.github.com> Date: Tue, 24 Oct 2023 13:49:26 +0800 Subject: [PATCH 1/8] Add docstring and use new version of telegram packages --- .../telegramBot/app.py" | 52 +++++++++++-------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git "a/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/app.py" "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/app.py" index 217fc61..2751952 100644 --- "a/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/app.py" +++ "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/app.py" @@ -1,41 +1,49 @@ import os -import telegram from flask import Flask, request -from telegram.ext import Dispatcher, MessageHandler, Filters, CallbackContext, CallbackQueryHandler -from telegram import InlineKeyboardMarkup, InlineKeyboardButton, Bot, Update, KeyboardButton, ReplyKeyboardMarkup +from telegram import Bot, Update +from telegram.ext import Dispatcher, MessageHandler, Filters, CallbackContext -# Initial Flask app -app = Flask(__name__) +# 初始化 Flask 應用 +app: Flask = Flask(__name__) -# 設定你的token -bot = telegram.Bot(token=('你的token')) -bot.send_message(chat_id = '你的ID', text ='你可以開始了') +# 設定你的 token +bot: Bot = Bot(token='你的 token') @app.route('/hook', methods=['POST']) -def webhook_handler(): - """Set route /hook with POST method will trigger this method.""" +def webhook_handler() -> str: + """ + 當路由 /hook 使用 POST 方法時,將觸發此方法。 + + Returns: + str: 回傳 'ok' 字串 + """ if request.method == "POST": - update = telegram.Update.de_json(request.get_json(force=True), bot) + update: Update = Update.de_json(request.get_json(force=True), bot) - # Update dispatcher process that handler to process this message + # 更新調度器處理程序以處理此訊息 dispatcher.process_update(update) return 'ok' -def reply_handler(update: Update, _: CallbackContext): - """自動回復""" +def reply_handler(update: Update, _: CallbackContext) -> None: + """ + 回覆處理程序。 + + Args: + update (Update): 從使用者接收到的更新訊息 + _ (CallbackContext): 回呼上下文,此處不使用,所以命名為 "_" + """ user = update.message.from_user - userText = update.message.text - update.message.reply_text(userText) + user_text = update.message.text + update.message.reply_text(user_text) -# New a dispatcher for bot -dispatcher = Dispatcher(bot, None) +# 為機器人新建一個調度器 +dispatcher: Dispatcher = Dispatcher(bot, None, use_context=True) -# Add handler for handling message, there are many kinds of message. For this handler, it particular handle text -# message. +# 為調度器添加處理程序,處理各種類型的訊息。此處的處理程序專門處理文字訊息。 dispatcher.add_handler(MessageHandler(Filters.text, reply_handler)) if __name__ == "__main__": - # Running server - port = int(os.environ.get('PORT', 27017)) + # 運行伺服器 + port: int = int(os.environ.get('PORT', 27017)) app.run(host='0.0.0.0', port=port) From a51ecaec7ce6998d573a327ef6a4699d6bf9e154 Mon Sep 17 00:00:00 2001 From: YiHungWONG <40423264+yihong1120@users.noreply.github.com> Date: Tue, 24 Oct 2023 13:51:10 +0800 Subject: [PATCH 2/8] Create Dockerfile --- .../telegramBot/Dockerfile" | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 "\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/Dockerfile" diff --git "a/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/Dockerfile" "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/Dockerfile" new file mode 100644 index 0000000..269e30a --- /dev/null +++ "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/Dockerfile" @@ -0,0 +1,17 @@ +# 使用官方 Python 基礎映像 +FROM python:3.11.5-slim + +# 設定工作目錄 +WORKDIR /app + +# 將當前目錄的內容複製到工作目錄中 +COPY . /app + +# 安裝所需的套件 +RUN pip install --no-cache-dir -r requirements.txt + +# 讓外部連線可以存取到 Flask 應用程式 +EXPOSE 5000 + +# 啟動 Flask 應用程式 +CMD ["python", "app.py"] From d90f2789d66edbaebb9901fc7364195b885cebcc Mon Sep 17 00:00:00 2001 From: YiHungWONG <40423264+yihong1120@users.noreply.github.com> Date: Tue, 24 Oct 2023 13:57:14 +0800 Subject: [PATCH 3/8] Create docker-compose.yml --- .../telegramBot/docker-compose.yml" | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 "\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/docker-compose.yml" diff --git "a/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/docker-compose.yml" "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/docker-compose.yml" new file mode 100644 index 0000000..55af8ca --- /dev/null +++ "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/docker-compose.yml" @@ -0,0 +1,8 @@ +version: '3.8' +services: + app: + build: . + ports: + - "5000:5000" + environment: + - FLASK_ENV=development From 57d651bafdf2bdae66bd99830e33669e83a53aa8 Mon Sep 17 00:00:00 2001 From: YiHungWONG <40423264+yihong1120@users.noreply.github.com> Date: Tue, 24 Oct 2023 14:04:22 +0800 Subject: [PATCH 4/8] Update requirements.txt --- .../telegramBot/requirements.txt" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/requirements.txt" "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/requirements.txt" index 31f8569..55471c3 100644 --- "a/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/requirements.txt" +++ "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/requirements.txt" @@ -1,14 +1,14 @@ certifi chardet click -flask +flask==2.3.3 future gunicorn idna itsdangerous jinja2 markupsafe -python-telegram-bot +python-telegram-bot==20.6 requests urllib3 werkzeug From 34753bbd49c1ba34ce995d9ace24ba46ad962e48 Mon Sep 17 00:00:00 2001 From: YiHungWONG <40423264+yihong1120@users.noreply.github.com> Date: Tue, 24 Oct 2023 14:19:05 +0800 Subject: [PATCH 5/8] Create README.md --- .../telegramBot/README.md" | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 "\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/README.md" diff --git "a/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/README.md" "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/README.md" new file mode 100644 index 0000000..e15aaaf --- /dev/null +++ "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/telegramBot/README.md" @@ -0,0 +1,36 @@ +# telegramBot + +這是一個使用 Flask 和 Telegram API 建立的機器人應用程式。 + +## 專案結構 + +``` +. +├── Dockerfile +├── docker-compose.yml +└── app.py +``` + +## 檔案說明 + +- `app.py`:這是主要的應用程式檔案,包含了 Flask 應用程式的初始化和路由設定,以及 Telegram 機器人的設定和訊息處理。 +- `Dockerfile`:這個檔案定義了 Docker 映像的建立過程,包括基礎映像的選擇、工作目錄的設定、應用程式檔案的複製、套件的安裝和應用程式的啟動。 +- `docker-compose.yml`:這個檔案定義了 Docker 容器的配置,包括映像的建立、端口的映射和環境變數的設定。 + +## 使用說明 + +1. 先確保你的電腦已經安裝了 Docker 和 Docker Compose。 +2. 將你的 Telegram 機器人 token 填入 `app.py` 中的對應位置。 +3. 在專案根目錄下執行 `docker-compose up` 命令來啟動應用程式。 +4. 你的應用程式現在應該已經在 http://localhost:5000/ 運行了。 + +## 注意事項 + +- 如果你在本地運行應用程式,請確保 5000 端口沒有被其他應用程式佔用。 +- 請確保你的 Telegram 機器人 token 是正確的,否則機器人將無法正常工作。 + +## 開發環境 + +- Python 3.11.5 +- Flask +- Telegram API From d2a38f2f6b4ab6732f028609565d1f0dc6d7261c Mon Sep 17 00:00:00 2001 From: YiHungWONG <40423264+yihong1120@users.noreply.github.com> Date: Wed, 25 Oct 2023 13:25:26 +0800 Subject: [PATCH 6/8] Refactor the code, add type hint and docstring --- .../Linebot-Basic/app.py" | 66 +++++++++++-------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git "a/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/Linebot-Basic/app.py" "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/Linebot-Basic/app.py" index 578c2bb..7e65890 100644 --- "a/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/Linebot-Basic/app.py" +++ "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/Linebot-Basic/app.py" @@ -1,50 +1,62 @@ -#載入LineBot所需要的套件 +# 載入LineBot所需要的套件 from flask import Flask, request, abort +from linebot import LineBotApi, WebhookHandler +from linebot.exceptions import InvalidSignatureError, LineBotApiError +from linebot.models import MessageEvent, TextMessage, TextSendMessage -from linebot import ( - LineBotApi, WebhookHandler -) -from linebot.exceptions import ( - InvalidSignatureError -) -from linebot.models import * - -app = Flask(__name__) +app: Flask = Flask(__name__) # 必須放上自己的Channel Access Token -line_bot_api = LineBotApi('你自己的token') +line_bot_api: LineBotApi = LineBotApi('你自己的token') # 必須放上自己的Channel Secret -handler = WebhookHandler('你自己的secret') +handler: WebhookHandler = WebhookHandler('你自己的secret') -line_bot_api.push_message('你自己的ID', TextSendMessage(text='你可以開始了')) +try: + line_bot_api.push_message('你自己的ID', TextSendMessage(text='你可以開始了')) +except LineBotApiError as e: + # 錯誤處理 + print(e.status_code) + print(e.error.message) + print(e.error.details) -# 監聽所有來自 /callback 的 Post Request @app.route("/callback", methods=['POST']) -def callback(): - # get X-Line-Signature header value - signature = request.headers['X-Line-Signature'] - - # get request body as text - body = request.get_data(as_text=True) +def callback() -> str: + """ + 監聽所有來自 /callback 的 Post Request + """ + # 取得 X-Line-Signature 標頭值 + signature: str = request.headers['X-Line-Signature'] + + # 取得 request body 文字 + body: str = request.get_data(as_text=True) app.logger.info("Request body: " + body) - # handle webhook body + # 處理 webhook body try: handler.handle(body, signature) except InvalidSignatureError: + print("無效的簽名。請檢查你的 channel access token/channel secret。") abort(400) return 'OK' -#訊息傳遞區塊 -##### 基本上程式編輯都在這個function ##### @handler.add(MessageEvent, message=TextMessage) -def handle_message(event): - message = TextSendMessage(text=event.message.text) - line_bot_api.reply_message(event.reply_token,message) +def handle_message(event: MessageEvent): + """ + 訊息傳遞區塊 + 基本上程式編輯都在這個function + """ + try: + message: TextSendMessage = TextSendMessage(text=event.message.text) + line_bot_api.reply_message(event.reply_token,message) + except LineBotApiError as e: + # 錯誤處理 + print(e.status_code) + print(e.error.message) + print(e.error.details) #主程式 import os if __name__ == "__main__": - port = int(os.environ.get('PORT', 5000)) + port: int = int(os.environ.get('PORT', 5000)) app.run(host='0.0.0.0', port=port) From f39a9417a59e1e42a18344d448f728a91096551f Mon Sep 17 00:00:00 2001 From: YiHungWONG <40423264+yihong1120@users.noreply.github.com> Date: Wed, 25 Oct 2023 13:32:06 +0800 Subject: [PATCH 7/8] Update requirements.txt --- .../Linebot-Basic/requirements.txt" | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git "a/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/Linebot-Basic/requirements.txt" "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/Linebot-Basic/requirements.txt" index aa98206..f329476 100644 --- "a/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/Linebot-Basic/requirements.txt" +++ "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/Linebot-Basic/requirements.txt" @@ -1,10 +1,2 @@ -line-bot-sdk -bs4 -flask -pymongo -datetime -pandas -SnowNLP -emoji -pyshorteners -scipy +line-bot-sdk==3.5.0 +flask==3.0.0 From a2d51094dda4368bf3a651f5e8315fc65c1535ff Mon Sep 17 00:00:00 2001 From: YiHungWONG <40423264+yihong1120@users.noreply.github.com> Date: Wed, 25 Oct 2023 13:35:15 +0800 Subject: [PATCH 8/8] Create README.md --- .../Linebot-Basic/README.md" | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 "\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/Linebot-Basic/README.md" diff --git "a/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/Linebot-Basic/README.md" "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/Linebot-Basic/README.md" new file mode 100644 index 0000000..6172a1c --- /dev/null +++ "b/\350\241\214\351\212\267\345\257\246\347\224\250\345\267\245\345\205\267/Linebot-Basic/README.md" @@ -0,0 +1,28 @@ +# Line Bot Python 程式碼 + +這是一個使用 Python 和 Flask 框架,以及 Line Messaging API 來建立 Line Bot 的範例程式碼。 + +## 環境設定 + +首先,你需要在你的 LINE Developers 控制台中建立一個新的 Messaging API 服務,並取得 Channel Access Token 和 Channel Secret。 + +然後,將這些資訊填入程式碼中對應的位置: + +```python +# 必須放上自己的Channel Access Token +line_bot_api: LineBotApi = LineBotApi('你自己的token') +# 必須放上自己的Channel Secret +handler: WebhookHandler = WebhookHandler('你自己的secret') +``` + +## 執行程式碼 + +你可以在本地或者伺服器上執行這個程式碼。如果你在本地運行,你可能需要使用 ngrok 或其他類似的工具來建立一個公開的網址,以便 Line 服務能夠訪問你的 webhook。 + +## 錯誤處理 + +這個程式碼包含了基本的錯誤處理。如果在處理 Line 事件或發送訊息時出現錯誤,程式碼會捕獲這個錯誤並打印出錯誤的詳細信息。 + +## 進一步學習 + +如果你想要進一步學習如何使用 Line Messaging API,你可以參考 [LINE Messaging API SDK for Python](https://github.com/line/line-bot-sdk-python) 的官方文件。