# Extensions – Your first Bot(翻譯)
###### tags: `telegram` `bot`
:::danger
[官方文件](https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions-%E2%80%93-Your-first-Bot)
:::
[TOC]
## Introduction
`telegram.ext`子模組是在純API實現基礎上建置的。它提供一個簡單易用的介面,並減輕程式設計師的負擔,不需要做[重覆性的工作(DRY)](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)。
它由幾個類別所組成,但兩個最重要的是[`telegram.ext.Updater`](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.updater.html#telegram.ext.Updater)與[`telegram.ext.Dispatcher`](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.dispatcher.html#telegram.ext.Dispatcher)
類別`Updater`不斷從telegram得到更新,然後將它們傳給類別`Dispatcher`。如果你建立一個`Updater`物件,它將為你建立一個`Dispatcher`,並將它們與`Queue`連結在一起。然後,你可以在Dispatcher中註冊不同的處理程序,它將依據你註冊的處理程序對`Updater`獲取得更新進行排序,並它將們傳給你所定義的callback function。
每一個處理程序都是類別[`telegram.ext.Handler`](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.handler.html#telegram.ext.Handler)的任何子類別的實例。這個套件為幾乎所有用例提供處理程序類,但是如果你需要一些特殊的東西,你也可以自己處理子類`Handler`。
首先,你需要一個Access Token。如果你已經閱讀並依循[API](https://github.com/python-telegram-bot/python-telegram-bot/wiki/Introduction-to-the-API)的介紹,那麼你可以使用你當時所生成的API。如果還沒:生成一個Access Token,你必須與[@BotFather](https://telegram.me/botfather)交談,然後通過一些簡單的步驟(見此說明)。你確實應該先[閱讀介紹](https://hackmd.io/Q5FnpJ8DTcWLWOU7OIAugg#6-BotFather)。
## Your first Bot, step-by-step
讓我們開始吧!同樣的,如果你要跟著這個教程,請啟動Pythom command line。
首先,你應該建立一個`Updater`物件。將`Token`以你的機器人的API token取代掉。
```python
from telegram.ext import Updater
updater = Updater(token='TOKEN', use_context=True)
```
**Related docs:** [telegram.ext.Updater](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.updater.html#telegram.ext.updater.Updater)
**注意:** `use_context=True`是一個特別的參數,只有套件版本12才需要。其預設值為`False`。它提供向下相容舊版本,並讓用戶有時間更新。版本13之後將會預設`use_context=True`。
為了更快地訪問`Updater`使用的`Dispatcher`,你可以在本地引入它:
```python
dispatcher = updater.dispatcher
```
這是一個設置`logging`模組的好時機,這樣你就會知道那些事沒有按預期執行:
```python
import logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)
```
**Note:** Read the article on [Exception Handling](https://github.com/python-telegram-bot/python-telegram-bot/wiki/Exception-Handling) if you want to learn more.
現在,你可以定義一個處理特殊類型的更新函數:
```python
def start(update, context):
context.bot.send_message(chat_id=update.effective_chat.id, text="I'm a bot, please talk to me!")
```
**Related docs:** [sendMessage](https://core.telegram.org/bots/api#sendmessage), [CallbackContext](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.callbackcontext.html) (the type of the context argument)
目標是每次機器人接收到包含`/start`命令的Telegram訊息的時候呼叫這個函數。要完成這個,你可以使用`CommandHandler`(提供的`Handler`之類之一)並在dispatcher中註冊它:
```python
from telegram.ext import CommandHandler
start_handler = CommandHandler('start', start)
dispatcher.add_handler(start_handler)
```
**Related docs:** [telegram.ext.CommandHandler](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.commandhandler.html), [telegram.ext.Dispatcher.add_handler](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.dispatcher.html#telegram.ext.dispatcher.Dispatcher.add_handler)
這就是你所需要的一切。開始機器人吧,執行:
```python
updater.start_polling()
```
**Related docs:** [telegram.ext.Updater.start_polling](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.updater.html#telegram.ext.updater.Updater.start_polling)
試一下吧!開啟一個與你的機器人的聊天室,並發出命令`/start` - 如果一切順利,它會回覆。
但我們的機器人現在只能回應命令`/start`。我們加入另一個程序處理,以監聽常規訊息。使用`MessageHandler`,另一個`Handler`子類,回應所有的文本訊息:
```python
def echo(update, context):
context.bot.send_message(chat_id=update.effective_chat.id, text=update.message.text)
from telegram.ext import MessageHandler, Filters
echo_handler = MessageHandler(Filters.text, echo)
dispatcher.add_handler(echo_handler)
```
Related docs: [telegram.ext.MessageHandler](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.messagehandler.html)
從現在開始,你的機器人應該能夠回應它接收到的所有非命令訊息。
**注意:** 一旦將新的處理程序加入`dispatcher`,它們將立即生效。
**注意:** 類別`Filters`包含一些函數,過濾傳入的文本訊息,影像,狀態更新,等等。對於傳給`MessageHandler`的過濾器,只要一個回傳True,那訊息都會收接收。如果你需要,你也可以寫屬於自己的過濾器。更多請參閱[Advanced Filters](https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions-%E2%80%93-Advanced-Filters)。
讓我們為你的機器人加入一些實際的功能。我們要實作一個命令`/caps`,它會將一些文本做為參數然後以大寫回覆。為了簡單起見,你可以接收傳遞給callback function中的命令的參數(`list`,以空格拆解):
```python
def caps(update, context):
text_caps = ' '.join(context.args).upper()
context.bot.send_message(chat_id=update.effective_chat.id, text=text_caps)
caps_handler = CommandHandler('caps', caps)
dispatcher.add_handler(caps_handler)
```
**注意:** 看一下`context.args`的用法。[CallbackContext](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.callbackcontext.html)有很多不同屬性,這取決於使用那一個程序處理。
Telegram Bot API的另一個很酷的功能就是[inline model](https://core.telegram.org/bots/inline)。如果你要為你的機器人實作inline功能,首先,與[@BotFather](https://telegram.me/botfather)交談,然後使用`/setinline`啟用inline mode。有時候它需要一段時間,一直到你的機器人在你的客戶端上註冊為inline(?)。 你可以透過重新啟動Telegram App來加快過程(或者,有時候你只需要等待一段時間)。
:::info
當BotFather詢問`Choose a bot to change inline queries status.`的時候,請回應`@your_bot_name`
:::
由於你的機器人明顯的是響叮噹的,讓我們繼續這個inline的主題。你現在可能已經知道流程,但這邊用了許多新類型,所以要稍微注意一下:
```python
from telegram import InlineQueryResultArticle, InputTextMessageContent
def inline_caps(update, context):
query = update.inline_query.query
if not query:
return
results = list()
results.append(
InlineQueryResultArticle(
id=query.upper(),
title='Caps',
input_message_content=InputTextMessageContent(query.upper())
)
)
context.bot.answer_inline_query(update.inline_query.id, results)
from telegram.ext import InlineQueryHandler
inline_caps_handler = InlineQueryHandler(inline_caps)
dispatcher.add_handler(inline_caps_handler)
```
**Related docs:** [telegram.ext.InlineQueryHandler](https://core.telegram.org/bots/api#answerinlinequery), [answerInlineQuery](https://python-telegram-bot.readthedocs.io/en/latest/telegram.ext.inlinequeryhandler.html)
還不賴!你的機器人現在可以按命令跟通過inline mode大叫了(哈!)
有些感到混亂的用戶也許會試著向機器人發送它們不瞭解的命令,因此你可以使用`MessageHanlder`搭配`command`過濾器來回覆之前處理程序不瞭解的所有命令。
```python
def unknown(update, context):
context.bot.send_message(chat_id=update.effective_chat.id, text="Sorry, I didn't understand that command.")
unknown_handler = MessageHandler(Filters.command, unknown)
dispatcher.add_handler(unknown_handler)
```
**注意:** 這個處理程序*必須*加在最後。如果你放在前面,那會在`CommandHandlers`有機會查看更新之前觸發它。處理完更新之後,所有其它處理程序都會被忽略。為了避免這種情況,你可以將關鍵參數組(int)傳給`add_handler`一個不是0的值。
如果你玩夠了,關閉機器人:
```python
updater.stop()
```
**注意:** 如你之前所讀,`Updater`在單獨的執行緒中執行。這對這個教程而言是非常好的,但如果你正在寫一些腳本,你可能想要透過`Ctrl+C`或發送信號到機器人程序來停止機器人。要這麼做,請使用`updater.idle()`。它會阻塞執行,一直到兩種情況之一發生,然後呼叫`updater.stop()`,然後繼續執行腳本。
下一步該讀什麼?
學習關於套件例外處理與最佳實踐,見[Exception Handling](https://github.com/python-telegram-bot/python-telegram-bot/wiki/Exception-Handling)
要更多的功能?查看[Extensions - JobQueue!](https://github.com/python-telegram-bot/python-telegram-bot/wiki/Extensions-%E2%80%93-JobQueue)
或者:在[examples folder](https://github.com/python-telegram-bot/python-telegram-bot/tree/master/examples)中透過我們的範例得到啟發。