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_edited forum_topic_reopened story
您可以在一个功能中使用某些类型。例子:
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分钟后而没有任何活动。
得到帮助。讨论。聊天。
加入新闻频道。在这里,我们将发布发布和更新。
模板是一个准备好的文件夹,其中包含基本项目的体系结构。以下是模板的一些示例:
想在这里列出您的机器人吗?只需提出拉动请求即可。仅接受具有公共源代码的机器人。