pytelegrambotapi
Telegram Bot API的簡單但可擴展的Python實現。
同步和異步。
支持的機器人API版本:7.1!
使用Python 3.8-3.12和PYPY 3對此API進行了測試。安裝庫有兩種方法:
$ pip install pyTelegramBotAPI
$ pip install git+https://github.com/eternnoir/pyTelegramBotAPI.git
通常建議使用第一個選項。
雖然API已經準備好生產,但仍在開發中,並且具有定期更新,請不要忘記通過致電定期更新它
pip install pytelegrambotapi --upgrade
假定您已經與@botfather獲得了API令牌。我們稱之為令牌TOKEN 。此外,您對Python編程語言具有基本知識,更重要的是Telegram Bot API。
Telebot類(以__init__.py定義)將所有API調用封裝在單個類中。它提供了諸如send_xyz ( send_message , send_document等)之類的功能,以及偵聽傳入消息的幾種方法。
創建一個名為echo_bot.py的文件。然後,打開文件並創建一個Telebot類的實例。
import telebot
bot = telebot . TeleBot ( "TOKEN" , parse_mode = None ) # You can set parse_mode by default. HTML or MARKDOWN注意:確保實際替換自己的API令牌。
聲明之後,我們需要註冊一些所謂的消息處理程序。消息處理程序定義了消息必須傳遞的過濾器。如果消息傳遞過濾器,則調用裝飾的功能,並將傳入消息作為參數傳遞。
讓我們定義一個處理傳入/start和/help命令的消息處理程序。
@ bot . message_handler ( commands = [ 'start' , 'help' ])
def send_welcome ( message ):
bot . reply_to ( message , "Howdy, how are you doing?" )消息處理程序裝飾的功能可以具有任意名稱,但是,它必須只有一個參數(消息) 。
讓我們添加另一個處理程序:
@ bot . message_handler ( func = lambda m : True )
def echo_all ( message ):
bot . reply_to ( message , message . text )這個迴聲將所有傳入的短信回到發件人。它使用lambda功能來測試消息。如果Lambda返回真實,則該消息將由裝飾的功能處理。由於我們希望所有消息都通過此功能處理,因此我們總是始終返回true。
注意:所有處理程序均以聲明的順序進行測試
現在,我們有了一個基本的機器人,該機器人回復了“/start”和“/help”命令的靜態消息,並迴盪了其餘的已發送消息。要啟動機器人,請在我們的源文件中添加以下內容:
bot . infinity_polling ()好吧,就是這樣!我們的源文件現在看起來像這樣:
import telebot
bot = telebot . TeleBot ( "YOUR_BOT_TOKEN" )
@ bot . message_handler ( commands = [ 'start' , 'help' ])
def send_welcome ( message ):
bot . reply_to ( message , "Howdy, how are you doing?" )
@ bot . message_handler ( func = lambda message : True )
def echo_all ( message ):
bot . reply_to ( message , message . text )
bot . infinity_polling ()要啟動機器人,只需打開一個終端並輸入python echo_bot.py即可運行機器人!通過發送命令(“/start”和“/help”)和任意文本消息來測試它。
所有類型均以類型定義。它們都完全符合Telegram API對類型的定義,除了from字段的消息,該消息已更名為from_user (因為from Python保留的令牌)。因此,可以通過message.message_id直接訪問message_id之類的屬性。請注意, message.chat可以是User或GroupChat的實例(請參閱Message.Chat中的用戶和groupChat?)。
消息對像還具有content_type屬性,該屬性定義了消息的類型。 content_type可以是以下字符串之一: text , audio , document , animation , game , photo , sticker , video , video_note ,語音, voice , location , contact , venue , dice ,dice,dice, new_chat_members , left_chat_member ,left_chat_title, group_chat_created , new_chat_photo new_chat_title delete_chat_photo , supergroup_chat_created channel_chat_created , migrate_to_chat_id , migrate_from_chat_id , pinned_message , invoice , successful_payment , connected_website , poll , passport_data , proximity_alert_triggered , video_chat_scheduled , video_chat_started , video_chat_ended , video_chat_participants_invited , web_app_data user_shared message_auto_delete_timer_changed general_forum_topic_hidden forum_topic_created general_forum_topic_unhidden forum_topic_closed chat_shared write_access_allowed forum_topic_reopened
您可以在一個功能中使用某些類型。例子:
content_types=["text", "sticker", "pinned_message", "photo", "audio"]
所有API方法都位於Telebot類中。他們被重命名為遵循普通的python命名約定。例如, getMe被重命名為get_me和sendMessage到send_message 。
下面概述了API的一些一般用例。
消息處理程序是一個用Telebot實例的message_handler裝飾器裝飾的函數。消息處理程序由一個或多個過濾器組成。每個過濾器必須返回某個消息的true,以使消息處理程序有資格處理該消息。以下方式聲明消息處理程序(前提是bot是Telebot的一個實例):
@ bot . message_handler ( filters )
def function_name ( message ):
bot . reply_to ( message , "This is a message handler" ) function_name不受任何限制。任何功能名稱都允許使用消息處理程序。該函數最多必須接受一個參數,這將是該函數必須處理的信息。 filters是關鍵字參數的列表。通過以下方式聲明過濾器: name=argument 。一個處理程序可能有多個過濾器。 Telebot支持以下過濾器:
| 姓名 | 參數 | 狀態 |
|---|---|---|
| content_types | 字符串列表(默認['text'] ) | 如果是message.content_type, True在字符串列表中。 |
| REGEXP | 正則表達式作為字符串 | True ,如果re.search(regexp_arg)返回True和message.content_type == 'text' (請參閱Python正則表達式) |
| 命令 | 字符串列表 | True ,如果message.content_type == 'text'和message.text從字符串列表中的命令開始。 |
| chat_types | 聊天類型列表 | True如果message.chat.type在您的過濾器中 |
| 功能 | 功能(lambda或功能參考) | 如果lambda或函數參考返回True True |
以下是使用過濾器和消息處理程序的一些示例:
import telebot
bot = telebot . TeleBot ( "TOKEN" )
# Handles all text messages that contains the commands '/start' or '/help'.
@ bot . message_handler ( commands = [ 'start' , 'help' ])
def handle_start_help ( message ):
pass
# Handles all sent documents and audio files
@ bot . message_handler ( content_types = [ 'document' , 'audio' ])
def handle_docs_audio ( message ):
pass
# Handles all text messages that match the regular expression
@ bot . message_handler ( regexp = "SOME_REGEXP" )
def handle_message ( message ):
pass
# Handles all messages for which the lambda returns True
@ bot . message_handler ( func = lambda message : message . document . mime_type == 'text/plain' , content_types = [ 'document' ])
def handle_text_doc ( message ):
pass
# Which could also be defined as:
def test_message ( message ):
return message . document . mime_type == 'text/plain'
@ bot . message_handler ( func = test_message , content_types = [ 'document' ])
def handle_text_doc ( message ):
pass
# Handlers can be stacked to create a function which will be called if either message_handler is eligible
# This handler will be called if the message starts with '/hello' OR is some emoji
@ bot . message_handler ( commands = [ 'hello' ])
@ bot . message_handler ( func = lambda msg : msg . text . encode ( "utf-8" ) == SOME_FANCY_EMOJI )
def send_something ( message ):
pass重要的是:所有處理程序均以聲明的順序進行測試
處理編輯的消息@bot.edited_message_handler(filters) # <- passes a Message type object to your function
處理頻道發布消息@bot.channel_post_handler(filters) # <- passes a Message type object to your function
處理編輯頻道帖子消息@bot.edited_channel_post_handler(filters) # <- passes a Message type object to your function
處理回調查詢
@ bot . callback_query_handler ( func = lambda call : True )
def test_callback ( call ): # <- passes a CallbackQuery type object to your function
logger . info ( call )處理運輸查詢@bot.shipping_query_handler() # <- passes a ShippingQuery type object to your function
處理pre checkoupt查詢@bot.pre_checkout_query_handler() # <- passes a PreCheckoutQuery type object to your function
處理民意調查更新@bot.poll_handler() # <- passes a Poll type object to your function
處理民意調查答案@bot.poll_answer_handler() # <- passes a PollAnswer type object to your function
處理chat @bot.my_chat_member_handler() # <- passes a ChatMemberUpdated type object to your function chat @bot.my_chat_member_handler()中的機器人成員狀態的更新
在聊天@bot.chat_member_handler() # <- passes a ChatMemberUpdated type object to your function註釋:“ chat_member”更新更新中,鍵入聊天成員的狀態的更新 @bot.chat_member_handler()#< - 默認不請求。如果要允許所有更新類型,請在bot.polling() / bot.infinity_polling()中設置allowed_updates to util.update_types
處理聊天聊天加入請求: @bot.chat_join_request_handler() # <- passes ChatInviteLink type object to your function
有關內聯模式的更多信息。
現在,您可以使用Inline_handler獲取Telebot中的直列查詢。
@ bot . inline_handler ( lambda query : query . query == 'text' )
def query_text ( inline_query ):
# Query message is text 使用Chosen_inline_handler在Telebot中獲取Chosen_inline_result。不要忘記為@botfather添加 /setInlinefeedback命令。
更多信息:收集反饋
@ bot . chosen_inline_handler ( func = lambda chosen_inline_result : True )
def test_chosen ( chosen_inline_result ):
# Process all chosen_inline_result. @ bot . inline_handler ( lambda query : query . query == 'text' )
def query_text ( inline_query ):
try :
r = types . InlineQueryResultArticle ( '1' , 'Result' , types . InputTextMessageContent ( 'Result message.' ))
r2 = types . InlineQueryResultArticle ( '2' , 'Result2' , types . InputTextMessageContent ( 'Result message2.' ))
bot . answer_inline_query ( inline_query . id , [ r , r2 ])
except Exception as e :
print ( e )中間件處理程序是一個函數,允許您修改請求或bot上下文,因為它們通過電報到達機器人。您可以想像中間件是在執行任何其他處理程序之前處理的邏輯連接鏈。默認情況下禁用中間件處理,通過設置apihelper.ENABLE_MIDDLEWARE = True來啟用它。
apihelper . ENABLE_MIDDLEWARE = True
@ bot . middleware_handler ( update_types = [ 'message' ])
def modify_message ( bot_instance , message ):
# modifying the message before it reaches any other handler
message . another_text = message . text + ':changed'
@ bot . message_handler ( commands = [ 'start' ])
def start ( message ):
# the message is already modified when it reaches message handler
assert message . another_text == message . text + ':changed'示例/中間件目錄中還有其他使用中間件處理程序的示例。
有基於班級的中間人。基於基礎類的中間件看起來像這樣:
class Middleware ( BaseMiddleware ):
def __init__ ( self ):
self . update_types = [ 'message' ]
def pre_process ( self , message , data ):
data [ 'foo' ] = 'Hello' # just for example
# we edited the data. now, this data is passed to handler.
# return SkipHandler() -> this will skip handler
# return CancelUpdate() -> this will cancel update
def post_process ( self , message , data , exception = None ):
print ( data [ 'foo' ])
if exception : # check for exception
print ( exception )基於類的中間件應該具有兩個功能:發布和預過程。因此,如您所見,基於班級的中間Wares在執行操作之前和之後工作。有關更多信息,請在示例中籤出
另外,您可以使用內置的自定義過濾器。或者,您可以創建自己的過濾器。
自定義過濾器的示例,我們上面有示例。檢查以下鏈接:您可以在源代碼中檢查一些內置過濾器,以通過ID進行過濾的示例,如果要添加一些內置過濾器,則歡迎將其添加到custic_filters.py文件中。這是創建過濾器類別的示例:
class IsAdmin ( telebot . custom_filters . SimpleCustomFilter ):
# Class will check whether the user is admin or creator in group or not
key = 'is_chat_admin'
@ staticmethod
def check ( message : telebot . types . Message ):
return bot . get_chat_member ( message . chat . id , message . from_user . id ). status in [ 'administrator' , 'creator' ]
# To register filter, you need to use method add_custom_filter.
bot . add_custom_filter ( IsAdmin ())
# Now, you can use it in handler.
@ bot . message_handler ( is_chat_admin = True )
def admin_of_group ( message ):
bot . send_message ( message . chat . id , 'You are admin of this group!' ) import telebot
TOKEN = '<token_string>'
tb = telebot . TeleBot ( TOKEN ) #create a new Telegram Bot object
# Upon calling this function, TeleBot starts polling the Telegram servers for new messages.
# - interval: int (default 0) - The interval between polling requests
# - timeout: integer (default 20) - Timeout in seconds for long polling.
# - allowed_updates: List of Strings (default None) - List of update types to request
tb . infinity_polling ( interval = 0 , timeout = 20 )
# getMe
user = tb . get_me ()
# setWebhook
tb . set_webhook ( url = "http://example.com" , certificate = open ( 'mycert.pem' ))
# unset webhook
tb . remove_webhook ()
# getUpdates
updates = tb . get_updates ()
# or
updates = tb . get_updates ( 1234 , 100 , 20 ) #get_Updates(offset, limit, timeout):
# sendMessage
tb . send_message ( chat_id , text )
# editMessageText
tb . edit_message_text ( new_text , chat_id , message_id )
# forwardMessage
tb . forward_message ( to_chat_id , from_chat_id , message_id )
# All send_xyz functions which can take a file as an argument, can also take a file_id instead of a file.
# sendPhoto
photo = open ( '/tmp/photo.png' , 'rb' )
tb . send_photo ( chat_id , photo )
tb . send_photo ( chat_id , "FILEID" )
# sendAudio
audio = open ( '/tmp/audio.mp3' , 'rb' )
tb . send_audio ( chat_id , audio )
tb . send_audio ( chat_id , "FILEID" )
## sendAudio with duration, performer and title.
tb . send_audio ( CHAT_ID , file_data , 1 , 'eternnoir' , 'pyTelegram' )
# sendVoice
voice = open ( '/tmp/voice.ogg' , 'rb' )
tb . send_voice ( chat_id , voice )
tb . send_voice ( chat_id , "FILEID" )
# sendDocument
doc = open ( '/tmp/file.txt' , 'rb' )
tb . send_document ( chat_id , doc )
tb . send_document ( chat_id , "FILEID" )
# sendSticker
sti = open ( '/tmp/sti.webp' , 'rb' )
tb . send_sticker ( chat_id , sti )
tb . send_sticker ( chat_id , "FILEID" )
# sendVideo
video = open ( '/tmp/video.mp4' , 'rb' )
tb . send_video ( chat_id , video )
tb . send_video ( chat_id , "FILEID" )
# sendVideoNote
videonote = open ( '/tmp/videonote.mp4' , 'rb' )
tb . send_video_note ( chat_id , videonote )
tb . send_video_note ( chat_id , "FILEID" )
# sendLocation
tb . send_location ( chat_id , lat , lon )
# sendChatAction
# action_string can be one of the following strings: 'typing', 'upload_photo', 'record_video', 'upload_video',
# 'record_audio', 'upload_audio', 'upload_document' or 'find_location'.
tb . send_chat_action ( chat_id , action_string )
# getFile
# Downloading a file is straightforward
# Returns a File object
import requests
file_info = tb . get_file ( file_id )
file = requests . get ( 'https://api.telegram.org/file/bot{0}/{1}' . format ( API_TOKEN , file_info . file_path ))
Telebot的所有send_xyz函數都採用可選的reply_markup參數。該參數必須是ReplyKeyboardMarkup , ReplyKeyboardRemove或ForceReply的一個實例,這些實例是按類型定義的。
from telebot import types
# Using the ReplyKeyboardMarkup class
# It's constructor can take the following optional arguments:
# - resize_keyboard: True/False (default False)
# - one_time_keyboard: True/False (default False)
# - selective: True/False (default False)
# - row_width: integer (default 3)
# row_width is used in combination with the add() function.
# It defines how many buttons are fit on each row before continuing on the next row.
markup = types . ReplyKeyboardMarkup ( row_width = 2 )
itembtn1 = types . KeyboardButton ( 'a' )
itembtn2 = types . KeyboardButton ( 'v' )
itembtn3 = types . KeyboardButton ( 'd' )
markup . add ( itembtn1 , itembtn2 , itembtn3 )
tb . send_message ( chat_id , "Choose one letter:" , reply_markup = markup )
# or add KeyboardButton one row at a time:
markup = types . ReplyKeyboardMarkup ()
itembtna = types . KeyboardButton ( 'a' )
itembtnv = types . KeyboardButton ( 'v' )
itembtnc = types . KeyboardButton ( 'c' )
itembtnd = types . KeyboardButton ( 'd' )
itembtne = types . KeyboardButton ( 'e' )
markup . row ( itembtna , itembtnv )
markup . row ( itembtnc , itembtnd , itembtne )
tb . send_message ( chat_id , "Choose one letter:" , reply_markup = markup )最後一個示例得出了以下結果:
# ReplyKeyboardRemove: hides a previously sent ReplyKeyboardMarkup
# Takes an optional selective argument (True/False, default False)
markup = types . ReplyKeyboardRemove ( selective = False )
tb . send_message ( chat_id , message , reply_markup = markup ) # ForceReply: forces a user to reply to a message
# Takes an optional selective argument (True/False, default False)
markup = types . ForceReply ( selective = False )
tb . send_message ( chat_id , "Send me another word:" , reply_markup = markup )前面:
該對象代表文本消息中的一個特殊實體。例如,主題標籤,用戶名,URL等。屬性:
typeurloffsetlengthuser以下是一個示例: message.entities[num].<attribute>
在這裡, num是回復中實體的實體號或順序,因為如果INCASE,答复/消息中有多個實體。
message.entities返回實體對象列表。
message.entities[0].type將提供第一個實體的類型
請參閱BOT API以獲取額外的詳細信息
由於Bot API的5.0版,您有可能運行自己的本地機器人API服務器。 Pytelegrambotapi還支持此功能。
from telebot import apihelper
apihelper . API_URL = "http://localhost:4200/bot{0}/{1}"重要的是:就像這裡所述,您必須在切換到本地API服務器之前從Telegram服務器登錄機器人。在pytelegrambotapi中使用bot.log_out()
注意:4200是一個示例端口
新:Telebot有異步實現。要啟用這種行為,請創建一個異步機器人而不是Telebot的實例。
tb = telebot . AsyncTeleBot ( "TOKEN" )現在,在單獨的異步任務中執行了調用Telegram API的每個函數。使用asynctelebot允許您執行以下操作:
import telebot
tb = telebot . AsyncTeleBot ( "TOKEN" )
@ tb . message_handler ( commands = [ 'start' ])
async def start_message ( message ):
await bot . send_message ( message . chat . id , 'Hello!' )在示例中查看更多
有時,您必鬚髮送超過5000個字符的消息。 Telegram API無法在一個請求中處理那麼多字符,因此我們需要以倍數為單位。這是使用API做到這一點的方法:
from telebot import util
large_text = open ( "large_text.txt" , "rb" ). read ()
# Split the text each 3000 characters.
# split_string returns a list with the splitted text.
splitted_text = util . split_string ( large_text , 3000 )
for text in splitted_text :
tb . send_message ( chat_id , text )或者,您可以使用新的smart_split函數來獲得更有意義的子字符串:
from telebot import util
large_text = open ( "large_text.txt" , "rb" ). read ()
# Splits one string into multiple strings, with a maximum amount of `chars_per_string` (max. 4096)
# Splits by last 'n', '. ' or ' ' in exactly this priority.
# smart_split returns a list with the splitted text.
splitted_text = util . smart_split ( large_text , chars_per_string = 3000 )
for text in splitted_text :
tb . send_message ( chat_id , text )Telebot構造函數採用以下可選論點:
作為消息處理程序的替代方案,還可以註冊函數作為Telebot的偵聽器。
注意:處理程序不會消失!您的消息將由處理人員和聽眾處理。同樣,由於線程的線程,不可能預測哪個最初會起作用。如果您使用螺紋= false,則自定義偵聽器將較早地工作,然後將其處理人員調用。例子:
def handle_messages ( messages ):
for message in messages :
# Do something with the message
bot . reply_to ( message , 'Hi' )
bot . set_update_listener ( handle_messages )
bot . infinity_polling ()使用Webhooks電報時,每次呼叫發送一個更新,對於處理它,您應該在收到它時致電process_new_messages([update.message])。
在示例/webhook_examples中使用Webhooks有一些示例。
您可以使用Telebot模塊Logger記錄有關Telebot的調試信息。使用telebot.logger獲取Telebot模塊的記錄器。可以將自定義記錄處理程序添加到記錄器中。有關更多信息,請參閱Python記錄模塊頁面。
import logging
logger = telebot . logger
telebot . logger . setLevel ( logging . DEBUG ) # Outputs debug messages to console.用於同步:
您可以使用代理進行請求。 apihelper.proxy對象將通過呼叫requests代理參數使用。
from telebot import apihelper
apihelper . proxy = { 'http' : 'http://127.0.0.1:3128' }如果要使用socket5代理,則需要安裝依賴關係pip install requests[socks] ,並確保您擁有最新版本的gunicorn , PySocks , pyTelegramBotAPI , requests和urllib3 。
apihelper . proxy = { 'https' : 'socks5://userproxy:password@proxy_address:port' }對於異步:
from telebot import asyncio_helper
asyncio_helper . proxy = 'http://127.0.0.1:3128' #url您可以使用使用
apihelper . CUSTOM_REQUEST_SENDER = your_handler範圍。您可以將自己的功能傳遞到那裡,而不是請求。
例如:
def custom_sender ( method , url , ** kwargs ):
print ( "custom_sender. method: {}, url: {}, params: {}" . format ( method , url , kwargs . get ( "params" )))
result = util . CustomRequestResponse ( '{"ok":true,"result":{"message_id": 1, "date": 1, "chat": {"id": 1, "type": "private"}}}' )
return result然後,您可以使用API並在處理程序代碼中繼續請求。
apihelper . CUSTOM_REQUEST_SENDER = custom_sender
tb = TeleBot ( "test" )
res = tb . send_message ( 123 , "Test" )結果將是:
custom_sender. method: post, url: https://api.telegram.org/botololo/sendMessage, params: {'chat_id': '123', 'text': 'Test'}
我們有一個完全異步的Telebot版本。此類不受線程控制。創建異步任務以執行所有內容。
Echo Bot onynctelebot示例:
# This is a simple echo bot using the decorator mechanism.
# It echoes any incoming text messages.
from telebot . async_telebot import AsyncTeleBot
import asyncio
bot = AsyncTeleBot ( 'TOKEN' )
# Handle '/start' and '/help'
@ bot . message_handler ( commands = [ 'help' , 'start' ])
async def send_welcome ( message ):
await bot . reply_to ( message , """
Hi there, I am EchoBot.
I am here to echo your kind words back to you. Just say anything nice and I'll say the exact same thing to you!
""" )
# Handle all other messages with content_type 'text' (content_types defaults to ['text'])
@ bot . message_handler ( func = lambda message : True )
async def echo_message ( message ):
await bot . reply_to ( message , message . text )
asyncio . run ( bot . polling ())如您在這裡所看到的,關鍵字在等待和異步。
異步任務取決於處理器性能。許多異步任務可以運行,而線程任務將相互阻止。
異步Bot是異步的。它使用AIOHTTP而不是請求模塊。
在我們的示例文件夾中查看更多示例
Telegram Bot API支持新的類型聊天。
Chat對像中的type屬性: if message . chat . type == "private" :
# private chat message
if message . chat . type == "group" :
# group chat message
if message . chat . type == "supergroup" :
# supergroup chat message
if message . chat . type == "channel" :
# channel message由於上次使用的會話超時,服務器發送消息時,服務器可能會拒絕長時間空閒的bot實例。將apihelper.SESSION_TIME_TO_LIVE = 5 * 60添加到您的初始化中,以強制娛樂5分鐘後而沒有任何活動。
得到幫助。討論。聊天。
加入新聞頻道。在這裡,我們將發布發布和更新。
模板是一個準備好的文件夾,其中包含基本項目的體系結構。以下是模板的一些示例:
想在這裡列出您的機器人嗎?只需提出拉動請求即可。僅接受具有公共源代碼的機器人。