Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
Hinrich Mahler edited this pageSep 10, 2023 ·182 revisions

This page can be read on its own to find the code snippet you need right now.

It is also a follow-up to the pageIntroduction to the API. If you come from there, you can leave your command line open and just try out a few of these snippets.

Pure API

Fetch updates

To fetch messages sent to your Bot, you can use thegetUpdates API method.

Note: You don't have to useget_updates if you are writing your bot with thetelegram.ext submodule, sincetelegram.ext.Updater takes care of fetching all updates for you. Read more about thathere.

updates=awaitbot.get_updates()print([u.message.textforuinupdates])

Fetch images sent to your Bot

updates=awaitbot.get_updates()print([u.message.photoforuinupdatesifu.message.photo])

Reply to messages

You'll always need thechat_id

chat_id= (awaitbot.get_updates())[-1].message.chat_id

General code snippets

These snippets usually apply to both ways of fetching updates. If you're usingtelegram.ext, you can get thechat_id in your handler callback withupdate.message.chat_id.

Note: In general, you can send messages to users by passing their user id as thechat_id.If the bot has a chat with the user, it will send the message to that chat.


Post a text message

ᵀᴱᴸᴱᴳᴿᴬᴹ

awaitbot.send_message(chat_id=chat_id,text="I'm sorry Dave I'm afraid I can't do that.")

Note:send_message method (as any ofsend_* methods ofBot class) returns the instance ofMessage class, so it can be used in code later.


Reply to a message

This is a shortcut tobot.send_message with same defaults. Read more about itin the docs.

awaitupdate.message.reply_text("I'm sorry Dave I'm afraid I can't do that.")

Note: There are equivalents of this method for replying with photos, audio etc., and similar shortcuts exist throughout the library.


Send a chat action

ᵀᴱᴸᴱᴳᴿᴬᴹUse this to tell the user that something is happening on the bot's side:

awaitbot.send_chat_action(chat_id=chat_id,action=telegram.constants.ChatAction.TYPING)

Alternatively, if you have several commands and don't want to repeat the above code snippet inside all commands seethis wiki section on how to do that.


Requesting location and contact from user

location_keyboard=telegram.KeyboardButton(text="send_location",request_location=True)contact_keyboard=telegram.KeyboardButton(text="send_contact",request_contact=True)custom_keyboard= [[location_keyboard,contact_keyboard ]]reply_markup=telegram.ReplyKeyboardMarkup(custom_keyboard)awaitbot.send_message(chat_id=chat_id, ...text="Would you mind sharing your location and contact with me?", ...reply_markup=reply_markup)

To catch the incoming message with the location/contact, useMessageHandler withfilters.LOCATION andfilters.CONTACT, respectively.


Message Formatting (bold, italic, code, ...)

Telegram supports some formatting options for text. All the details about what is supported can be foundhere. Please keep in mind that you will have to escape the special characters as detailed in the documentation. PTB also offers ahelper function for escaping of Markdown text. For escaping of HTML text, you can usehtml.escape from the standard library.

You can format text with every API method/type that has aparse_mode parameter. In addition to editing your text as described in the link above, pass one of the parse modes available throughtelegram.constants.ParseMode to theparse_mode parameter. Since the5.0 update of the Bot API (version13.1+ of PTB), you can alternatively pass a list oftelegram.MessageEntities to theentities parameter.

Note: In the API 4.5 update, Telegram introduced MarkdownV2, which supports nested entities and needs other escaping than v1. Markdown V1 is referred as legacy mode by the official API docs, and you should prefer MarkdownV2. Make sure to also usereply_markdown_v2 instead ofreply_markdown etc.

Post a text message with Markdown formatting

ᵀᴱᴸᴱᴳᴿᴬᴹ

awaitbot.send_message(chat_id=chat_id,text="*bold* _italic_ `fixed width font` [link](http://google.com)\.",parse_mode=telegram.constants.ParseMode.MARKDOWN_V2)

Post a text message with HTML formatting

ᵀᴱᴸᴱᴳᴿᴬᴹ

awaitbot.send_message(chat_id=chat_id,text='<b>bold</b> <i>italic</i> <a href="http://google.com">link</a>.',parse_mode=telegram.constants.ParseMode.HTML)

Message entities

ᵀᴱᴸᴱᴳᴿᴬᴹTo useMessageEntity, extract the entities and their respective text from aMessage object usingparse_entities.

Note: This method should always be used instead of theentities attribute, since it calculates the correct substring from the message text based on UTF-16 codepoints - that is, it extracts the correct string even on when working with weird characters such as Emojis.

Consider this example which checks for presence of URLs in a message and prints them on screen.

# A dictionary that maps entity to textentities=message.parse_entities()forentinentities:txt=entities[ent]ifent.type==ent.TEXT_LINK:# Text with embedded URLprint(f"{txt} -{ent.url}")elifent.type==ent.URL:# Plain URLprint(txt)

For more narrowed use cases like extracting only Telegram message links, you might be better usingptbcontrib/extract_urls.


Telegram formatting to BBCode

This is an example how to use entities to convert Telegram formatting to BBCode. In the current version it doesnot support nested entities.

Define parsing function:

Click to expand

importsysdefparse_bbcode(message_text,entities,urled=False):"""BBCode parsing function"""ifmessage_textisNone:returnNoneifnotsys.maxunicode==0xffff:message_text=message_text.encode('utf-16-le')bbcode_text=''last_offset=0forentity,textinsorted(entities.items(),key=(lambdaitem:item[0].offset)):ifentity.type=='text_link':insert='[url={}]{}[/url]'.format(entity.url,text)elifentity.type=='mention':insert='[url=https://t.me/{0}]{1}[/url]'.format(text.strip('@'),text)elifentity.type=='url'andurled:insert='[url={0}]{0}[/url]'.format(text)elifentity.type=='bold':insert='[b]'+text+'[/b]'elifentity.type=='italic':insert='[i]'+text+'[/i]'elifentity.type=='underline':insert='[u]'+text+'[/u]'elifentity.type=='strikethrough':insert='[s]'+text+'[/s]'elifentity.type=='code':insert='[code]'+text+'[/code]'elifentity.type=='pre':insert='[pre]'+text+'[/pre]'else:insert=textifsys.maxunicode==0xffff:bbcode_text+=message_text[last_offset:entity.offset]+insertelse:bbcode_text+=message_text[last_offset*2:entity.offset*2].decode('utf-16-le')+insertlast_offset=entity.offset+entity.lengthifsys.maxunicode==0xffff:bbcode_text+=message_text[last_offset:]else:bbcode_text+=message_text[last_offset*2:].decode('utf-16-le')returnbbcode_text

Call it with:

entities=update.message.parse_entities()bbcode=parse_bbcode(update.message.text,entities,urled=True)

...or for photo captions:

entities=update.message.parse_caption_entities()bbcode=parse_bbcode(caption,entities,urled=True)

bbcode will contain message/caption text formatted in BBCode.urled parameter determines if URLs in text are to be processed as links or left as text.


Keyboard Menus

Custom Keyboards

ᵀᴱᴸᴱᴳᴿᴬᴹ

custom_keyboard= [['top-left','top-right'],                    ['bottom-left','bottom-right']]reply_markup=telegram.ReplyKeyboardMarkup(custom_keyboard)awaitbot.send_message(chat_id=chat_id,text="Custom Keyboard Test",reply_markup=reply_markup)

See also:Build a menu with Buttons


Remove a custom keyboard

reply_markup=telegram.ReplyKeyboardRemove()awaitbot.send_message(chat_id=chat_id,text="I'm back.",reply_markup=reply_markup)

Other useful stuff

Generate flag emojis from country codes

The Unicode flag emoji for any country can by definition be calculated from the countries2 letter country code. The following snippet only works in Python 3.

OFFSET=127462-ord('A')defflag(code):code=code.upper()returnchr(ord(code[0])+OFFSET)+chr(ord(code[1])+OFFSET)>>>flag('un')'🇺🇳'>>>flag('eu')'🇪🇺'

Map a Slot Machine Dice value to the corresponding symbols

The 🎰 dice can take the values 1-64. Here is a dictionary that maps each value to the unique combination of symbols that produce that value:

(Source: ThisGist by@Chase22)

Click to expand

slot_machine_value= {1: ("bar","bar","bar"),2: ("grape","bar","bar"),3: ("lemon","bar","bar"),4: ("seven","bar","bar"),5: ("bar","grape","bar"),6: ("grape","grape","bar"),7: ("lemon","grape","bar"),8: ("seven","grape","bar"),9: ("bar","lemon","bar"),10: ("grape","lemon","bar"),11: ("lemon","lemon","bar"),12: ("seven","lemon","bar"),13: ("bar","seven","bar"),14: ("grape","seven","bar"),15: ("lemon","seven","bar"),16: ("seven","seven","bar"),17: ("bar","bar","grape"),18: ("grape","bar","grape"),19: ("lemon","bar","grape"),20: ("seven","bar","grape"),21: ("bar","grape","grape"),22: ("grape","grape","grape"),23: ("lemon","grape","grape"),24: ("seven","grape","grape"),25: ("bar","lemon","grape"),26: ("grape","lemon","grape"),27: ("lemon","lemon","grape"),28: ("seven","lemon","grape"),29: ("bar","seven","grape"),30: ("grape","seven","grape"),31: ("lemon","seven","grape"),32: ("seven","seven","grape"),33: ("bar","bar","lemon"),34: ("grape","bar","lemon"),35: ("lemon","bar","lemon"),36: ("seven","bar","lemon"),37: ("bar","grape","lemon"),38: ("grape","grape","lemon"),39: ("lemon","grape","lemon"),40: ("seven","grape","lemon"),41: ("bar","lemon","lemon"),42: ("grape","lemon","lemon"),43: ("lemon","lemon","lemon"),44: ("seven","lemon","lemon"),45: ("bar","seven","lemon"),46: ("grape","seven","lemon"),47: ("lemon","seven","lemon"),48: ("seven","seven","lemon"),49: ("bar","bar","seven"),50: ("grape","bar","seven"),51: ("lemon","bar","seven"),52: ("seven","bar","seven"),53: ("bar","grape","seven"),54: ("grape","grape","seven"),55: ("lemon","grape","seven"),56: ("seven","grape","seven"),57: ("bar","lemon","seven"),58: ("grape","lemon","seven"),59: ("lemon","lemon","seven"),60: ("seven","lemon","seven"),61: ("bar","seven","seven"),62: ("grape","seven","seven"),63: ("lemon","seven","seven"),64: ("seven","seven","seven"),}

Get the new members message

importasynciofromtelegramimportUpdatefromtelegram.extimportContextTypesasyncdefadd_group(update:Update,context:ContextTypes.DEFAULT_TYPE):awaitasyncio.gather(update.message.reply_text(f"{member.full_name} just joined the group")formemberinupdate.message.new_chat_members    )add_group_handle=MessageHandler(filters.StatusUpdate.NEW_CHAT_MEMBERS,add_group)application.add_handler(add_group_handle)

Note that service messages about non-bot users joining the chat are removed from large groups. You can get the new members message by following thechatmemberbot.py example.


Exclude forwarded channel posts in discussion groups from MessageHandlers

If you're usingMessageHandlers and do not want them to respond to the channel posts automatically forwarded to the discussion group linked to your channel, you can use this filter in yourMessageHandler (requires PTB v13.9+):

~filters.IS_AUTOMATIC_FORWARD

Exclude Messages from anonymous Admins

If you're usingMessageHandlers and do not want them to respond to messages from anonymous admins, you can use this filter in yourMessageHandler:

~filters.SenderChat.SUPER_GROUP

Advanced snippets

Register a function as a command handler (decorator)

This decorator allows you to register a function as a command handler in aFlask like manner.

defcommand_handler(command):defdecorator(func):handler=CommandHandler(command,func)application.add_handler(handler)returnfuncreturndecorator
Usage

Add the@command_handler(command) decorator on top of your handler function:

@command_handler("hello")asyncdefhello(update,context):awaitcontext.bot.send_message(chat_id=update.effective_chat.id,text="Hello world!")

Note: You can modify this decorator in order to register any type of handler (seeTypes Of Handlers). Please also note that PTB deliberately does not provide such functionality out of the box due to the reasons mentioned in#899.


Restrict access to a handler (decorator)

This decorator allows you to restrict the access of a handler to only theuser_ids specified inLIST_OF_ADMINS.

fromfunctoolsimportwrapsLIST_OF_ADMINS= [12345678,87654321]defrestricted(func):@wraps(func)asyncdefwrapped(update,context,*args,**kwargs):user_id=update.effective_user.idifuser_idnotinLIST_OF_ADMINS:print(f"Unauthorized access denied for{user_id}.")returnreturnawaitfunc(update,context,*args,**kwargs)returnwrapped
Usage

Add a@restricted decorator on top of your handler declaration:

@restrictedasyncdefmy_handler(update,context):pass# only accessible if `user_id` is in `LIST_OF_ADMINS`.

Send action while handling command (decorator)

This parametrized decorator allows you to signal different actions depending on the type of response of your bot. This way users will have similar feedback from your bot as they would from a real human.

fromfunctoolsimportwrapsdefsend_action(action):"""Sends `action` while processing func command."""defdecorator(func):@wraps(func)asyncdefcommand_func(update,context,*args,**kwargs):awaitcontext.bot.send_chat_action(chat_id=update.effective_message.chat_id,action=action)returnawaitfunc(update,context,*args,**kwargs)returncommand_funcreturndecorator
Usage

Result

You can decorate handler callbacks directly with@send_action(ChatAction.<Action>) or create aliases and decorate with them (more readable) .

send_typing_action=send_action(ChatAction.TYPING)send_upload_video_action=send_action(ChatAction.UPLOAD_VIDEO)send_upload_photo_action=send_action(ChatAction.UPLOAD_PHOTO)

With the above aliases, the following decorators are equivalent

@send_typing_actionasyncdefmy_handler(update,context):pass# user will see 'typing' while your bot is handling the request.@send_action(ChatAction.TYPING)asyncdefmy_handler(update,context):pass# user will see 'typing' while your bot is handling the request.

All possible actions are documentedhere.


Build a menu with Buttons

Often times you will find yourself in need for a menu with dynamic content. Use the followingbuild_menu method to create a button layout withn_cols columns out of a list ofbuttons.

fromtypingimportUnion,ListfromtelegramimportInlineKeyboardButtondefbuild_menu(buttons:List[InlineKeyboardButton],n_cols:int,header_buttons:Union[InlineKeyboardButton,List[InlineKeyboardButton]]=None,footer_buttons:Union[InlineKeyboardButton,List[InlineKeyboardButton]]=None)->List[List[InlineKeyboardButton]]:menu= [buttons[i:i+n_cols]foriinrange(0,len(buttons),n_cols)]ifheader_buttons:menu.insert(0,header_buttonsifisinstance(header_buttons,list)else [header_buttons])iffooter_buttons:menu.append(footer_buttonsifisinstance(footer_buttons,list)else [footer_buttons])returnmenu

You can use theheader_buttons andfooter_buttons lists to put buttons in the first or last row respectively.

Usage

Output

Replace the... in below snippet by an appropriate argument, as indicated in theInlineKeyboardButton documentation. If you want to useKeyboardButtons, useReplyKeyboardMarkup instead ofInlineKeyboardMarkup.

button_list= [InlineKeyboardButton("col1",callback_data=...),InlineKeyboardButton("col2",callback_data=...),InlineKeyboardButton("row 2",callback_data=...)]reply_markup=InlineKeyboardMarkup(util.build_menu(button_list,n_cols=2))awaitbot.send_message(...,"A two-column menu",reply_markup=reply_markup)

Or, if you need a dynamic version, use list comprehension to generate yourbutton_list dynamically from a list of strings:

some_strings= ["col1","col2","row2"]button_list= [[KeyboardButton(s)]forsinsome_strings]

This is especially useful if put inside a helper method likeget_data_buttons to work on dynamic data and updating the menu according to user input.

To handle thecallback_data, you need to set aCallbackQueryHandler.


Verify data fromTelegram Web Login Widget.

When using aLoginUrl in anInlineKeyboardButton to authorize a user on your website via Telegram, you'll have to to check the hash of the received data to verify the data of the integrity as describedhere

The data JSON data will have the following form:

{"id":XXXXXXXXX"first_name":"XXX""last_name":"XXX""username":"XXXXX""photo_url":"https://t.meXXXXXX.jpg""auth_date":XXXXXXXXXX"hash":"XXXXXXXXXXXXXXXXXXXXXX....."}

The following is an example implementation in Python:

Click to expand

importhashlibimporthmacBOT_TOKEN='YOUR BOT TOKEN'defverify(request_data):request_data=request_data.copy()tg_hash=request_data['hash']request_data.pop('hash',None)request_data_alphabetical_order=sorted(request_data.items(),key=lambdax:x[0])data_check_string= []fordata_pairinrequest_data_alphabetical_order:key,value=data_pair[0],data_pair[1]data_check_string.append(f"{key}={value}")data_check_string='\n'.join(data_check_string)secret_key=hashlib.sha256(BOT_TOKEN.encode()).digest()received_hash=hmac.new(secret_key,msg=data_check_string.encode(),digestmod=hashlib.sha256).hexdigest()ifreceived_hash==tg_hash:# The user clicked to the Auth Button and data is verified.print('User Logged in.')returnTrueelse:# The data is not validprint('User data mis-matched.')returnFalse# Optionally use another if-else block to check the auth_date in order to prevent outdated data from being verified.

A sample of Flask app can be foundhere.


Simple way of restarting the bot

The following example allows you to restart the bot from within a handler.It goes without saying that you should protect this method from access by unauthorized users - seehere for some tips on this.The main magic consists of callingApplication.stop_running from within a handler callback to allow for a graceful shutdown.Actually restarting the python script can then be achieved by different means.

Click to expand

importosimportsysfromtelegramimportUpdatefromtelegram.extimportContextTypes,Application,CommandHandlerasyncdefrestart(update:Update,context:ContextTypes.DEFAULT_TYPE)->None:context.bot_data["restart"]=Truecontext.application.stop_running()defmain()->None:application=Application.builder().token("TOKEN").build()application.bot_data["restart"]=Falseapplication.add_handler(CommandHandler("restart",restart))application.run_polling(allowed_updates=Update.ALL_TYPES)ifapplication.bot_data["restart"]:os.execl(sys.executable,sys.executable,*sys.argv)if__name__=="__main__":main()

Wiki ofpython-telegram-bot © Copyright 2015-2025 – Licensed byCreative Commons

Must read

  1. Introduction to the API
  2. Tutorial: Your first bot
  3. FAQ
  4. How to ask good questions
  5. How to write an MWE

Concepts & Important Elements

  1. Architecture Overview
  2. Builder Pattern forApplication
  3. Types of Handlers
  4. Working with Files and Media
  5. Exceptions, Warnings and Logging
  6. Concurrency in PTB

Notable Features

  1. Advanced Filters
  2. Storing data
  3. Making your bot persistent
  4. Adding Defaults
  5. Job Queue
  6. Arbitrarycallback_data
  7. Avoiding flood limits
  8. Webhooks
  9. Bot API Forward Compatiblity

Code Resources

  1. Frequently requested design patterns
  2. Code snippets
  3. Performance Optimizations
  4. Telegram Passport
  5. Bots built with PTB
  6. Automated Bot Tests

Examples explained

  1. InlineKeyboard Example

Networking

  1. Working Behind a Proxy
  2. Handling network errors

Other resources

  1. Where to host Telegram Bots
  2. How to host your bot
  3. Local API Server
  4. Type Checking with PTB
  5. Press
  6. Notes on GAE
  7. Related Projects
  8. Emoji

Transition Guides

Administration

Clone this wiki locally

[8]ページ先頭

©2009-2025 Movatter.jp